package com.tencent.mm.sdk.openapi;

import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import com.tencent.mm.sdk.a.a.b;
import com.tencent.mm.sdk.modelbase.BaseReq;
import com.tencent.mm.sdk.modelbase.BaseResp;
import com.tencent.mm.sdk.modelbiz.AddCardToWXCardPackage.Resp;
import com.tencent.mm.sdk.modelmsg.GetMessageFromWX.Req;
import com.tencent.mm.sdk.modelmsg.LaunchFromWX.Req;
import com.tencent.mm.sdk.modelmsg.SendAuth.Resp;
import com.tencent.mm.sdk.modelmsg.SendMessageToWX.Resp;
import com.tencent.mm.sdk.modelmsg.ShowMessageFromWX.Req;
import com.tencent.mm.sdk.modelpay.PayResp;

final class WXApiImplV10 implements IWXAPI {

    private static final String TAG = "MicroMsg.SDK.WXApiImplV10";

    private static String wxappPayEntryClassname = null;

    private String appId;

    private boolean checkSignature = false;

    private Context context;

    private boolean detached = false;

    WXApiImplV10(Context paramContext, String paramString, boolean paramBoolean) {
        com.tencent.mm.sdk.b.a.c("MicroMsg.SDK.WXApiImplV10", "<init>, appId = " + paramString + ", checkSignature = " + paramBoolean);
        this.context = paramContext;
        this.appId = paramString;
        this.checkSignature = paramBoolean;
    }

    private boolean checkSumConsistent(byte[] paramArrayOfByte1, byte[] paramArrayOfByte2) {
        if ((paramArrayOfByte1 == null) || (paramArrayOfByte1.length == 0) || (paramArrayOfByte2 == null) || (paramArrayOfByte2.length == 0)) {
            com.tencent.mm.sdk.b.a.a("MicroMsg.SDK.WXApiImplV10", "checkSumConsistent fail, invalid arguments");
            return false;
        }
        if (paramArrayOfByte1.length != paramArrayOfByte2.length) {
            com.tencent.mm.sdk.b.a.a("MicroMsg.SDK.WXApiImplV10", "checkSumConsistent fail, length is different");
            return false;
        }
        for (int i = 0; ; i++) {
            if (i >= paramArrayOfByte1.length)
                break label66;
            if (paramArrayOfByte1[i] != paramArrayOfByte2[i])
                break;
        }
        label66: return true;
    }

    private boolean sendAddCardToWX(Context paramContext, Bundle paramBundle) {
        ContentResolver localContentResolver = par

        Uri localUri = Uri.parse("content://com.tencent.mm.sdk.comm.provider/addCardToWX");
        String[] arrayOfString = new String[3];
        arrayOfString[0] = this.appId;
        arrayOfString[1] = paramBundle.getString("_wxapi_add_card_to_wx_card_list");
        arrayOfString[2] = paramBundle.getString("_wxapi_basereq_transaction");
        Cursor localCursor = localContentResolver.query(localUri, null, null, arrayOfString, null);
        if (localCursor != null)
            localCursor.close();
        return true;
    }

    private boolean sendJumpToBizProfileReq(Context paramContext, Bundle paramBundle) {
        ContentResolver localContentResolver = paramContext.getContentResolver();
        Uri localUri = Uri.parse("content://com.tencent.mm.sdk.comm.provider/jumpToBizProfile");
        String[] arrayOfString = new String[5];
        arrayOfString[0] = this.appId;
        arrayOfString[1] = paramBundle.getString("_wxapi_jump_to_biz_profile_req_to_user_name");
        arrayOfString[2] = paramBundle.getString("_wxapi_jump_to_biz_profile_req_ext_msg");
        arrayOfString[3] = paramBundle.getInt("_wxapi_jump_to_biz_profile_req_scene");
        arrayOfString[4] = paramBundle.getInt("_wxapi_jump_to_biz_profile_req_profile_type");
        Cursor localCursor = localContentResolver.query(localUri, null, null, arrayOfString, null);
        if (localCursor != null)
            localCursor.close();
        return true;
    }

    private boolean sendJumpToBizWebviewReq(Context paramContext, Bundle paramBundle) {
        ContentResolver localContentResolver = paramContext.getContentResolver();
        Uri localUri = Uri.parse("content://com.tencent.mm.sdk.comm.provider/jumpToBizProfile");
        String[] arrayOfString = new String[4];
        arrayOfString[0] = this.appId;
        arrayOfString[1] = paramBundle.getString("_wxapi_jump_to_biz_webview_req_to_user_name");
        arrayOfString[2] = paramBundle.getString("_wxapi_jump_to_biz_webview_req_ext_msg");
        arrayOfString[3] = paramBundle.getInt("_wxapi_jump_to_biz_webview_req_scene");
        Cursor localCursor = localContentResolver.query(localUri, null, null, arrayOfString, null);
        if (localCursor != null)
            localCursor.close();
        return true;
    }

    private boolean sendPayReq(Context paramContext, Bundle paramBundle) {
        if (wxappPayEntryClassname == null) {
            wxappPayEntryClassname = new MMSharedPreferences(paramContext).getString("_wxapp_pay_entry_classname_", null);
            com.tencent.mm.sdk.b.a.c("MicroMsg.SDK.WXApiImplV10", "pay, set wxappPayEntryClassname = " + wxappPayEntryClassname);
            if (wxappPayEntryClassname == null) {
                com.tencent.mm.sdk.b.a.a("MicroMsg.SDK.WXApiImplV10", "pay fail, wxappPayEntryClassname is null");
                return false;
            }
        }
        com.tencent.mm.sdk.a.a.a locala = new com.tencent.mm.sdk.a.a.a();
        locala.e = paramBundle;
        locala.b = "com.tencent.mm";
        locala.c = wxappPayEntryClassname;
        return com.tencent.mm.sdk.a.a.a(paramContext, locala);
    }

    public final void detach() {
        com.tencent.mm.sdk.b.a.c("MicroMsg.SDK.WXApiImplV10", "detach");
        this.detached = true;
        this.context = null;
    }

    public final int getWXAppSupportAPI() {
        if (this.detached)
            throw new IllegalStateException("getWXAppSupportAPI fail, WXMsgImpl has been detached");
        if (!isWXAppInstalled()) {
            com.tencent.mm.sdk.b.a.a("MicroMsg.SDK.WXApiImplV10", "open wx app failed, not installed or signature check failed");
            return 0;
        }
        return new MMSharedPreferences(this.context).getInt("_build_info_sdk_int_", 0);
    }

    public final boolean handleIntent(Intent paramIntent, IWXAPIEventHandler paramIWXAPIEventHandler) {
        if (!WXApiImplComm.isIntentFromWx(paramIntent, "com.tencent.mm.openapi.token")) {
            com.tencent.mm.sdk.b.a.b("MicroMsg.SDK.WXApiImplV10", "handleIntent fail, intent not from weixin msg");
            return false;
        }
        if (this.detached)
            throw new IllegalStateException("handleIntent fail, WXMsgImpl has been detached");
        String str1 = paramIntent.getStringExtra("_mmessage_content");
        int i = paramIntent.getIntExtra("_mmessage_sdkVersion", 0);
        String str2 = paramIntent.getStringExtra("_mmessage_appPackage");
        if ((str2 == null) || (str2.length() == 0)) {
            com.tencent.mm.sdk.b.a.a("MicroMsg.SDK.WXApiImplV10", "invalid argument");
            return false;
        }
        if (!checkSumConsistent(paramIntent.getByteArrayExtra("_mmessage_checksum"), b.a(str1, i, str2))) {
            com.tencent.mm.sdk.b.a.a("MicroMsg.SDK.WXApiImplV10", "checksum fail");
            return false;
        }
        int j = paramIntent.getIntExtra("_wxapi_command_type", 0);
        switch(j) {
            case 7:
            case 8:
            default:
                com.tencent.mm.sdk.b.a.a("MicroMsg.SDK.WXApiImplV10", "unknown cmd = " + j);
                return false;
            case 1:
                paramIWXAPIEventHandler.onResp(new SendAuth.Resp(paramIntent.getExtras()));
                return true;
            case 2:
                paramIWXAPIEventHandler.onResp(new SendMessageToWX.Resp(paramIntent.getExtras()));
                return true;
            case 3:
                paramIWXAPIEventHandler.onReq(new GetMessageFromWX.Req(paramIntent.getExtras()));
                return true;
            case 4:
                paramIWXAPIEventHandler.onReq(new ShowMessageFromWX.Req(paramIntent.getExtras()));
                return true;
            case 5:
                paramIWXAPIEventHandler.onResp(new PayResp(paramIntent.getExtras()));
                return true;
            case 6:
                paramIWXAPIEventHandler.onReq(new LaunchFromWX.Req(paramIntent.getExtras()));
                return true;
            case 9:
        }
        paramIWXAPIEventHandler.onResp(new AddCardToWXCardPackage.Resp(paramIntent.getExtras()));
        return true;
    }

    public final boolean isWXAppInstalled() {
        if (this.detached)
            throw new IllegalStateException("isWXAppInstalled fail, WXMsgImpl has been detached");
        try {
            PackageInfo localPackageInfo = this.context.getPackageManager().getPackageInfo("com.tencent.mm", 64);
            if (localPackageInfo == null)
                return false;
            boolean bool = WXApiImplComm.validateAppSignature(this.context, localPackageInfo.signatures, this.checkSignature);
            return bool;
        } catch (PackageManager.NameNotFoundException localNameNotFoundException) {
        }
        return false;
    }

    public final boolean isWXAppSupportAPI() {
        if (this.detached)
            throw new IllegalStateException("isWXAppSupportAPI fail, WXMsgImpl has been detached");
        return getWXAppSupportAPI() >= 570490883;
    }

    public final boolean openWXApp() {
        if (this.detached)
            throw new IllegalStateException("openWXApp fail, WXMsgImpl has been detached");
        if (!isWXAppInstalled()) {
            com.tencent.mm.sdk.b.a.a("MicroMsg.SDK.WXApiImplV10", "open wx app failed, not installed or signature check failed");
            return false;
        }
        try {
            this.context.startActivity(this.context.getPackageManager().getLaunchIntentForPackage("com.tencent.mm"));
            return true;
        } catch (Exception localException) {
            com.tencent.mm.sdk.b.a.a("MicroMsg.SDK.WXApiImplV10", "startActivity fail, exception = " + localException.getMessage());
        }
        return false;
    }

    public final boolean registerApp(String paramString) {
        if (this.detached)
            throw new IllegalStateException("registerApp fail, WXMsgImpl has been detached");
        if (!WXApiImplComm.validateAppSignatureForPackage(this.context, "com.tencent.mm", this.checkSignature)) {
            com.tencent.mm.sdk.b.a.a("MicroMsg.SDK.WXApiImplV10", "register app failed for wechat app signature check failed");
            return false;
        }
        com.tencent.mm.sdk.b.a.c("MicroMsg.SDK.WXApiImplV10", "registerApp, appId = " + paramString);
        if (paramString != null)
            this.appId = paramString;
        com.tencent.mm.sdk.b.a.c("MicroMsg.SDK.WXApiImplV10", "register app " + this.context.getPackageName());
        com.tencent.mm.sdk.a.a.a.a locala = new com.tencent.mm.sdk.a.a.a.a();
        locala.f = "com.tencent.mm";
        locala.g = "com.tencent.mm.plugin.openapi.Intent.ACTION_HANDLE_APP_REGISTER";
        locala.d = ("weixin://registerapp?appid=" + this.appId);
        return com.tencent.mm.sdk.a.a.a.a(this.context, locala);
    }

    public final boolean sendReq(BaseReq paramBaseReq) {
        if (this.detached)
            throw new IllegalStateException("sendReq fail, WXMsgImpl has been detached");
        if (!WXApiImplComm.validateAppSignatureForPackage(this.context, "com.tencent.mm", this.checkSignature)) {
            com.tencent.mm.sdk.b.a.a("MicroMsg.SDK.WXApiImplV10", "sendReq failed for wechat app signature check failed");
            return false;
        }
        if (!paramBaseReq.checkArgs()) {
            com.tencent.mm.sdk.b.a.a("MicroMsg.SDK.WXApiImplV10", "sendReq checkArgs fail");
            return false;
        }
        com.tencent.mm.sdk.b.a.c("MicroMsg.SDK.WXApiImplV10", "sendReq, req type = " + paramBaseReq.getType());
        Bundle localBundle = new Bundle();
        paramBaseReq.toBundle(localBundle);
        if (paramBaseReq.getType() == 5)
            return sendPayReq(this.context, localBundle);
        if (paramBaseReq.getType() == 7)
            return sendJumpToBizProfileReq(this.context, localBundle);
        if (paramBaseReq.getType() == 8)
            return sendJumpToBizWebviewReq(this.context, localBundle);
        if (paramBaseReq.getType() == 9)
            return sendAddCardToWX(this.context, localBundle);
        com.tencent.mm.sdk.a.a.a locala = new com.tencent.mm.sdk.a.a.a();
        locala.e = localBundle;
        locala.d = ("weixin://sendreq?appid=" + this.appId);
        locala.b = "com.tencent.mm";
        locala.c = "com.tencent.mm.plugin.base.stub.WXEntryActivity";
        return com.tencent.mm.sdk.a.a.a(this.context, locala);
    }

    public final boolean sendResp(BaseResp paramBaseResp) {
        if (this.detached)
            throw new IllegalStateException("sendResp fail, WXMsgImpl has been detached");
        if (!WXApiImplComm.validateAppSignatureForPackage(this.context, "com.tencent.mm", this.checkSignature)) {
            com.tencent.mm.sdk.b.a.a("MicroMsg.SDK.WXApiImplV10", "sendResp failed for wechat app signature check failed");
            return false;
        }
        if (!paramBaseResp.checkArgs()) {
            com.tencent.mm.sdk.b.a.a("MicroMsg.SDK.WXApiImplV10", "sendResp checkArgs fail");
            return false;
        }
        Bundle localBundle = new Bundle();
        paramBaseResp.toBundle(localBundle);
        com.tencent.mm.sdk.a.a.a locala = new com.tencent.mm.sdk.a.a.a();
        locala.e = localBundle;
        locala.d = ("weixin://sendresp?appid=" + this.appId);
        locala.b = "com.tencent.mm";
        locala.c = "com.tencent.mm.plugin.base.stub.WXEntryActivity";
        return com.tencent.mm.sdk.a.a.a(this.context, locala);
    }

    public final void unregisterApp() {
        if (this.detached)
            throw new IllegalStateException("unregisterApp fail, WXMsgImpl has been detached");
        if (!WXApiImplComm.validateAppSignatureForPackage(this.context, "com.tencent.mm", this.checkSignature)) {
            com.tencent.mm.sdk.b.a.a("MicroMsg.SDK.WXApiImplV10", "unregister app failed for wechat app signature check failed");
            return;
        }
        com.tencent.mm.sdk.b.a.c("MicroMsg.SDK.WXApiImplV10", "unregisterApp, appId = " + this.appId);
        if ((this.appId == null) || (this.appId.length() == 0)) {
            com.tencent.mm.sdk.b.a.a("MicroMsg.SDK.WXApiImplV10", "unregisterApp fail, appId is empty");
            return;
        }
        com.tencent.mm.sdk.b.a.c("MicroMsg.SDK.WXApiImplV10", "unregister app " + this.context.getPackageName());
        com.tencent.mm.sdk.a.a.a.a locala = new com.tencent.mm.sdk.a.a.a.a();
        locala.f = "com.tencent.mm";
        locala.g = "com.tencent.mm.plugin.openapi.Intent.ACTION_HANDLE_APP_UNREGISTER";
        locala.d = ("weixin://unregisterapp?appid=" + this.appId);
        com.tencent.mm.sdk.a.a.a.a(this.context, locala);
    }
}


for (int i = 0; ; i++) {
            if (i >= paramArrayOfByte1.length)
                break label66;
            if (paramArrayOfByte1[i] != paramArrayOfByte2[i])
                break;
        }

package com.tencent.mm.sdk.openapi;

import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import com.tencent.mm.sdk.a.a.b;
import com.tencent.mm.sdk.modelbase.BaseReq;
import com.tencent.mm.sdk.modelbase.BaseResp;
import com.tencent.mm.sdk.modelbiz.AddCardToWXCardPackage.Resp;
import com.tencent.mm.sdk.modelmsg.GetMessageFromWX.Req;
import com.tencent.mm.sdk.modelmsg.LaunchFromWX.Req;
import com.tencent.mm.sdk.modelmsg.SendAuth.Resp;
import com.tencent.mm.sdk.modelmsg.SendMessageToWX.Resp;
import com.tencent.mm.sdk.modelmsg.ShowMessageFromWX.Req;
import com.tencent.mm.sdk.modelpay.PayResp;

final class WXApiImplV10 implements IWXAPI {

    private static final String TAG = "MicroMsg.SDK.WXApiImplV10";

    private static String wxappPayEntryClassname = null;

    private String appId;

    private boolean checkSignature = false;

    private Context context;

    private boolean detached = false;

    WXApiImplV10(Context paramContext, String paramString, boolean paramBoolean) {
        com.tencent.mm.sdk.b.a.c("MicroMsg.SDK.WXApiImplV10", "<init>, appId = " + paramString + ", checkSignature = " + paramBoolean);
        this.context = paramContext;
        this.appId = paramString;
        this.checkSignature = paramBoolean;
    }

    private boolean checkSumConsistent(byte[] paramArrayOfByte1, byte[] paramArrayOfByte2) {
        if ((paramArrayOfByte1 == null) || (paramArrayOfByte1.length == 0) || (paramArrayOfByte2 == null) || (paramArrayOfByte2.length == 0)) {
            com.tencent.mm.sdk.b.a.a("MicroMsg.SDK.WXApiImplV10", "checkSumConsistent fail, invalid arguments");
            return false;
        }
        if (paramArrayOfByte1.length != paramArrayOfByte2.length) {
            com.tencent.mm.sdk.b.a.a("MicroMsg.SDK.WXApiImplV10", "checkSumConsistent fail, length is different");
            return false;
        }

        label66: return true;
    }

    private boolean sendAddCardToWX(Context paramContext, Bundle paramBundle) {
        ContentResolver localContentResolver = paramContext.getContentResolver();
        Uri localUri = Uri.parse("content://com.tencent.mm.sdk.comm.provider/addCardToWX");
        String[] arrayOfString = new String[3];
        arrayOfString[0] = this.appId;
        arrayOfString[1] = paramBundle.getString("_wxapi_add_card_to_wx_card_list");
        arrayOfString[2] = paramBundle.getString("_wxapi_basereq_transaction");
        Cursor localCursor = localContentResolver.query(localUri, null, null, arrayOfString, null);
        if (localCursor != null)
            localCursor.close();
        return true;
    }

    private boolean sendJumpToBizProfileReq(Context paramContext, Bundle paramBundle) {
        ContentResolver localContentResolver = paramContext.getContentResolver();
        Uri localUri = Uri.parse("content://com.tencent.mm.sdk.comm.provider/jumpToBizProfile");
        String[] arrayOfString = new String[5];
        arrayOfString[0] = this.appId;
        arrayOfString[1] = paramBundle.getString("_wxapi_jump_to_biz_profile_req_to_user_name");
        arrayOfString[2] = paramBundle.getString("_wxapi_jump_to_biz_profile_req_ext_msg");
        arrayOfString[3] = paramBundle.getInt("_wxapi_jump_to_biz_profile_req_scene");
        arrayOfString[4] = paramBundle.getInt("_wxapi_jump_to_biz_profile_req_profile_type");
        Cursor localCursor = localContentResolver.query(localUri, null, null, arrayOfString, null);
        if (localCursor != null)
            localCursor.close();
        return true;
    }

    private boolean sendJumpToBizWebviewReq(Context paramContext, Bundle paramBundle) {
        ContentResolver localContentResolver = paramContext.getContentResolver();
        Uri localUri = Uri.parse("content://com.tencent.mm.sdk.comm.provider/jumpToBizProfile");
        String[] arrayOfString = new String[4];
        arrayOfString[0] = this.appId;
        arrayOfString[1] = paramBundle.getString("_wxapi_jump_to_biz_webview_req_to_user_name");
        arrayOfString[2] = paramBundle.getString("_wxapi_jump_to_biz_webview_req_ext_msg");
        arrayOfString[3] = paramBundle.getInt("_wxapi_jump_to_biz_webview_req_scene");
        Cursor localCursor = localContentResolver.query(localUri, null, null, arrayOfString, null);
        if (localCursor != null)
            localCursor.close();
        return true;
    }

    private boolean sendPayReq(Context paramContext, Bundle paramBundle) {
        if (wxappPayEntryClassname == null) {
            wxappPayEntryClassname = new MMSharedPreferences(paramContext).getString("_wxapp_pay_entry_classname_", null);
            com.tencent.mm.sdk.b.a.c("MicroMsg.SDK.WXApiImplV10", "pay, set wxappPayEntryClassname = " + wxappPayEntryClassname);
            if (wxappPayEntryClassname == null) {
                com.tencent.mm.sdk.b.a.a("MicroMsg.SDK.WXApiImplV10", "pay fail, wxappPayEntryClassname is null");
                return false;
            }
        }
        com.tencent.mm.sdk.a.a.a locala = new com.tencent.mm.sdk.a.a.a();
        locala.e = paramBundle;
        locala.b = "com.tencent.mm";
        locala.c = wxappPayEntryClassname;
        return com.tencent.mm.sdk.a.a.a(paramContext, locala);
    }

    public final void detach() {
        com.tencent.mm.sdk.b.a.c("MicroMsg.SDK.WXApiImplV10", "detach");
        this.detached = true;
        this.context = null;
    }

    public final int getWXAppSupportAPI() {
        if (this.detached)
            throw new IllegalStateException("getWXAppSupportAPI fail, WXMsgImpl has been detached");
        if (!isWXAppInstalled()) {
            com.tencent.mm.sdk.b.a.a("MicroMsg.SDK.WXApiImplV10", "open wx app failed, not installed or signature check failed");
            return 0;
        }
        return new MMSharedPreferences(this.context).getInt("_build_info_sdk_int_", 0);
    }

    public final boolean handleIntent(Intent paramIntent, IWXAPIEventHandler paramIWXAPIEventHandler) {
        if (!WXApiImplComm.isIntentFromWx(paramIntent, "com.tencent.mm.openapi.token")) {
            com.tencent.mm.sdk.b.a.b("MicroMsg.SDK.WXApiImplV10", "handleIntent fail, intent not from weixin msg");
            return false;
        }
        if (this.detached)
            throw new IllegalStateException("handleIntent fail, WXMsgImpl has been detached");
        String str1 = paramIntent.getStringExtra("_mmessage_content");
        int i = paramIntent.getIntExtra("_mmessage_sdkVersion", 0);
        String str2 = paramIntent.getStringExtra("_mmessage_appPackage");
        if ((str2 == null) || (str2.length() == 0)) {
            com.tencent.mm.sdk.b.a.a("MicroMsg.SDK.WXApiImplV10", "invalid argument");
            return false;
        }
        if (!checkSumConsistent(paramIntent.getByteArrayExtra("_mmessage_checksum"), b.a(str1, i, str2))) {
            com.tencent.mm.sdk.b.a.a("MicroMsg.SDK.WXApiImplV10", "checksum fail");
            return false;
        }
        int j = paramIntent.getIntExtra("_wxapi_command_type", 0);
        switch(j) {
            case 7:
            case 8:
            default:
                com.tencent.mm.sdk.b.a.a("MicroMsg.SDK.WXApiImplV10", "unknown cmd = " + j);
                return false;
            case 1:
                paramIWXAPIEventHandler.onResp(new SendAuth.Resp(paramIntent.getExtras()));
                return true;
            case 2:
                paramIWXAPIEventHandler.onResp(new SendMessageToWX.Resp(paramIntent.getExtras()));
                return true;
            case 3:
                paramIWXAPIEventHandler.onReq(new GetMessageFromWX.Req(paramIntent.getExtras()));
                return true;
            case 4:
                paramIWXAPIEventHandler.onReq(new ShowMessageFromWX.Req(paramIntent.getExtras()));
                return true;
            case 5:
                paramIWXAPIEventHandler.onResp(new PayResp(paramIntent.getExtras()));
                return true;
            case 6:
                paramIWXAPIEventHandler.onReq(new LaunchFromWX.Req(paramIntent.getExtras()));
                return true;
            case 9:
        }
        paramIWXAPIEventHandler.onResp(new AddCardToWXCardPackage.Resp(paramIntent.getExtras()));
        return true;
    }

    public final boolean isWXAppInstalled() {
        if (this.detached)
            throw new IllegalStateException("isWXAppInstalled fail, WXMsgImpl has been detached");
        try {
            PackageInfo localPackageInfo = this.context.getPackageManager().getPackageInfo("com.tencent.mm", 64);
            if (localPackageInfo == null)
                return false;
            boolean bool = WXApiImplComm.validateAppSignature(this.context, localPackageInfo.signatures, this.checkSignature);
            return bool;
        } catch (PackageManager.NameNotFoundException localNameNotFoundException) {
        }
        return false;
    }

    public final boolean isWXAppSupportAPI() {
        if (this.detached)
            throw new IllegalStateException("isWXAppSupportAPI fail, WXMsgImpl has been detached");
        return getWXAppSupportAPI() >= 570490883;
    }

    public final boolean openWXApp() {
        if (this.detached)
            throw new IllegalStateException("openWXApp fail, WXMsgImpl has been detached");
        if (!isWXAppInstalled()) {
            com.tencent.mm.sdk.b.a.a("MicroMsg.SDK.WXApiImplV10", "open wx app failed, not installed or signature check failed");
            return false;
        }
        try {
            this.context.startActivity(this.context.getPackageManager().getLaunchIntentForPackage("com.tencent.mm"));
            return true;
        } catch (Exception localException) {
            com.tencent.mm.sdk.b.a.a("MicroMsg.SDK.WXApiImplV10", "startActivity fail, exception = " + localException.getMessage());
        }
        return false;
    }

    public final boolean registerApp(String paramString) {
        if (this.detached)
            throw new IllegalStateException("registerApp fail, WXMsgImpl has been detached");
        if (!WXApiImplComm.validateAppSignatureForPackage(this.context, "com.tencent.mm", this.checkSignature)) {
            com.tencent.mm.sdk.b.a.a("MicroMsg.SDK.WXApiImplV10", "register app failed for wechat app signature check failed");
            return false;
        }
        com.tencent.mm.sdk.b.a.c("MicroMsg.SDK.WXApiImplV10", "registerApp, appId = " + paramString);
        if (paramString != null)
            this.appId = paramString;
        com.tencent.mm.sdk.b.a.c("MicroMsg.SDK.WXApiImplV10", "register app " + this.context.getPackageName());
        com.tencent.mm.sdk.a.a.a.a locala = new com.tencent.mm.sdk.a.a.a.a();
        locala.f = "com.tencent.mm";
        locala.g = "com.tencent.mm.plugin.openapi.Intent.ACTION_HANDLE_APP_REGISTER";
        locala.d = ("weixin://registerapp?appid=" + this.appId);
        return com.tencent.mm.sdk.a.a.a.a(this.context, locala);
    }

    public final boolean sendReq(BaseReq paramBaseReq) {
        if (this.detached)
            throw new IllegalStateException("sendReq fail, WXMsgImpl has been detached");
        if (!WXApiImplComm.validateAppSignatureForPackage(this.context, "com.tencent.mm", this.checkSignature)) {
            com.tencent.mm.sdk.b.a.a("MicroMsg.SDK.WXApiImplV10", "sendReq failed for wechat app signature check failed");
            return false;
        }
        if (!paramBaseReq.checkArgs()) {
            com.tencent.mm.sdk.b.a.a("MicroMsg.SDK.WXApiImplV10", "sendReq checkArgs fail");
            return false;
        }
        com.tencent.mm.sdk.b.a.c("MicroMsg.SDK.WXApiImplV10", "sendReq, req type = " + paramBaseReq.getType());
        Bundle localBundle = new Bundle();
        paramBaseReq.toBundle(localBundle);
        if (paramBaseReq.getType() == 5)
            return sendPayReq(this.context, localBundle);
        if (paramBaseReq.getType() == 7)
            return sendJumpToBizProfileReq(this.context, localBundle);
        if (paramBaseReq.getType() == 8)
            return sendJumpToBizWebviewReq(this.context, localBundle);
        if (paramBaseReq.getType() == 9)
            return sendAddCardToWX(this.context, localBundle);
        com.tencent.mm.sdk.a.a.a locala = new com.tencent.mm.sdk.a.a.a();
        locala.e = localBundle;
        locala.d = ("weixin://sendreq?appid=" + this.appId);
        locala.b = "com.tencent.mm";
        locala.c = "com.tencent.mm.plugin.base.stub.WXEntryActivity";
        return com.tencent.mm.sdk.a.a.a(this.context, locala);
    }

    public final boolean sendResp(BaseResp paramBaseResp) {
        if (this.detached)
            throw new IllegalStateException("sendResp fail, WXMsgImpl has been detached");
        if (!WXApiImplComm.validateAppSignatureForPackage(this.context, "com.tencent.mm", this.checkSignature)) {
            com.tencent.mm.sdk.b.a.a("MicroMsg.SDK.WXApiImplV10", "sendResp failed for wechat app signature check failed");
            return false;
        }
        if (!paramBaseResp.checkArgs()) {
            com.tencent.mm.sdk.b.a.a("MicroMsg.SDK.WXApiImplV10", "sendResp checkArgs fail");
            return false;
        }
        Bundle localBundle = new Bundle();
        paramBaseResp.toBundle(localBundle);
        com.tencent.mm.sdk.a.a.a locala = new com.tencent.mm.sdk.a.a.a();
        locala.e = localBundle;
        locala.d = ("weixin://sendresp?appid=" + this.appId);
        locala.b = "com.tencent.mm";
        locala.c = "com.tencent.mm.plugin.base.stub.WXEntryActivity";
        return com.tencent.mm.sdk.a.a.a(this.context, locala);
    }

    public final void unregisterApp() {
        if (this.detached)
            throw new IllegalStateException("unregisterApp fail, WXMsgImpl has been detached");
        if (!WXApiImplComm.validateAppSignatureForPackage(this.context, "com.tencent.mm", this.checkSignature)) {
            com.tencent.mm.sdk.b.a.a("MicroMsg.SDK.WXApiImplV10", "unregister app failed for wechat app signature check failed");
            return;
        }
        com.tencent.mm.sdk.b.a.c("MicroMsg.SDK.WXApiImplV10", "unregisterApp, appId = " + this.appId);
        if ((this.appId == null) || (this.appId.length() == 0)) {
            com.tencent.mm.sdk.b.a.a("MicroMsg.SDK.WXApiImplV10", "unregisterApp fail, appId is empty");
            return;
        }
        com.tencent.mm.sdk.b.a.c("MicroMsg.SDK.WXApiImplV10", "unregister app " + this.context.getPackageName());
        com.tencent.mm.sdk.a.a.a.a locala = new com.tencent.mm.sdk.a.a.a.a();
        locala.f = "com.tencent.mm";
        locala.g = "com.tencent.mm.plugin.openapi.Intent.ACTION_HANDLE_APP_UNREGISTER";
        locala.d = ("weixin://unregisterapp?appid=" + this.appId);
        com.tencent.mm.sdk.a.a.a.a(this.context, locala);
    }
}


try {
            PackageInfo localPackageInfo = this.context.getPackageManager().getPackageInfo("com.tencent.mm", 64);
            if (localPackageInfo == null)
                return false;
            boolean bool = WXApiImplComm.validateAppSignature(this.context, localPackageInfo.signatures, this.checkSignature);
            return bool;
        } catch (PackageManager.NameNotFoundException localNameNotFoundException) {
        }

package com.tencent.mm.sdk.openapi;

import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import com.tencent.mm.sdk.a.a.b;
import com.tencent.mm.sdk.modelbase.BaseReq;
import com.tencent.mm.sdk.modelbase.BaseResp;
import com.tencent.mm.sdk.modelbiz.AddCardToWXCardPackage.Resp;
import com.tencent.mm.sdk.modelmsg.GetMessageFromWX.Req;
import com.tencent.mm.sdk.modelmsg.LaunchFromWX.Req;
import com.tencent.mm.sdk.modelmsg.SendAuth.Resp;
import com.tencent.mm.sdk.modelmsg.SendMessageToWX.Resp;
import com.tencent.mm.sdk.modelmsg.ShowMessageFromWX.Req;
import com.tencent.mm.sdk.modelpay.PayResp;

final class WXApiImplV10 implements IWXAPI {

    private static final String TAG = "MicroMsg.SDK.WXApiImplV10";

    private static String wxappPayEntryClassname = null;

    private String appId;

    private boolean checkSignature = false;

    private Context context;

    private boolean detached = false;

    WXApiImplV10(Context paramContext, String paramString, boolean paramBoolean) {
        com.tencent.mm.sdk.b.a.c("MicroMsg.SDK.WXApiImplV10", "<init>, appId = " + paramString + ", checkSignature = " + paramBoolean);
        this.context = paramContext;
        this.appId = paramString;
        this.checkSignature = paramBoolean;
    }

    private boolean checkSumConsistent(byte[] paramArrayOfByte1, byte[] paramArrayOfByte2) {
        if ((paramArrayOfByte1 == null) || (paramArrayOfByte1.length == 0) || (paramArrayOfByte2 == null) || (paramArrayOfByte2.length == 0)) {
            com.tencent.mm.sdk.b.a.a("MicroMsg.SDK.WXApiImplV10", "checkSumConsistent fail, invalid arguments");
            return false;
        }
        if (paramArrayOfByte1.length != paramArrayOfByte2.length) {
            com.tencent.mm.sdk.b.a.a("MicroMsg.SDK.WXApiImplV10", "checkSumConsistent fail, length is different");
            return false;
        }
        for (int i = 0; ; i++) {
            if (i >= paramArrayOfByte1.length)
                break label66;
            if (paramArrayOfByte1[i] != paramArrayOfByte2[i])
                break;
        }
        label66: return true;
    }

    private boolean sendAddCardToWX(Context paramContext, Bundle paramBundle) {
        ContentResolver localContentResolver = paramContext.getContentResolver();
        Uri localUri = Uri.parse("content://com.tencent.mm.sdk.comm.provider/addCardToWX");
        String[] arrayOfString = new String[3];
        arrayOfString[0] = this.appId;
        arrayOfString[1] = paramBundle.getString("_wxapi_add_card_to_wx_card_list");
        arrayOfString[2] = paramBundle.getString("_wxapi_basereq_transaction");
        Cursor localCursor = localContentResolver.query(localUri, null, null, arrayOfString, null);
        if (localCursor != null)
            localCursor.close();
        return true;
    }

    private boolean sendJumpToBizProfileReq(Context paramContext, Bundle paramBundle) {
        ContentResolver localContentResolver = paramContext.getContentResolver();
        Uri localUri = Uri.parse("content://com.tencent.mm.sdk.comm.provider/jumpToBizProfile");
        String[] arrayOfString = new String[5];
        arrayOfString[0] = this.appId;
        arrayOfString[1] = paramBundle.getString("_wxapi_jump_to_biz_profile_req_to_user_name");
        arrayOfString[2] = paramBundle.getString("_wxapi_jump_to_biz_profile_req_ext_msg");
        arrayOfString[3] = paramBundle.getInt("_wxapi_jump_to_biz_profile_req_scene");
        arrayOfString[4] = paramBundle.getInt("_wxapi_jump_to_biz_profile_req_profile_type");
        Cursor localCursor = localContentResolver.query(localUri, null, null, arrayOfString, null);
        if (localCursor != null)
            localCursor.close();
        return true;
    }

    private boolean sendJumpToBizWebviewReq(Context paramContext, Bundle paramBundle) {
        ContentResolver localContentResolver = paramContext.getContentResolver();
        Uri localUri = Uri.parse("content://com.tencent.mm.sdk.comm.provider/jumpToBizProfile");
        String[] arrayOfString = new String[4];
        arrayOfString[0] = this.appId;
        arrayOfString[1] = paramBundle.getString("_wxapi_jump_to_biz_webview_req_to_user_name");
        arrayOfString[2] = paramBundle.getString("_wxapi_jump_to_biz_webview_req_ext_msg");
        arrayOfString[3] = paramBundle.getInt("_wxapi_jump_to_biz_webview_req_scene");
        Cursor localCursor = localContentResolver.query(localUri, null, null, arrayOfString, null);
        if (localCursor != null)
            localCursor.close();
        return true;
    }

    private boolean sendPayReq(Context paramContext, Bundle paramBundle) {
        if (wxappPayEntryClassname == null) {
            wxappPayEntryClassname = new MMSharedPreferences(paramContext).getString("_wxapp_pay_entry_classname_", null);
            com.tencent.mm.sdk.b.a.c("MicroMsg.SDK.WXApiImplV10", "pay, set wxappPayEntryClassname = " + wxappPayEntryClassname);
            if (wxappPayEntryClassname == null) {
                com.tencent.mm.sdk.b.a.a("MicroMsg.SDK.WXApiImplV10", "pay fail, wxappPayEntryClassname is null");
                return false;
            }
        }
        com.tencent.mm.sdk.a.a.a locala = new com.tencent.mm.sdk.a.a.a();
        locala.e = paramBundle;
        locala.b = "com.tencent.mm";
        locala.c = wxappPayEntryClassname;
        return com.tencent.mm.sdk.a.a.a(paramContext, locala);
    }

    public final void detach() {
        com.tencent.mm.sdk.b.a.c("MicroMsg.SDK.WXApiImplV10", "detach");
        this.detached = true;
        this.context = null;
    }

    public final int getWXAppSupportAPI() {
        if (this.detached)
            throw new IllegalStateException("getWXAppSupportAPI fail, WXMsgImpl has been detached");
        if (!isWXAppInstalled()) {
            com.tencent.mm.sdk.b.a.a("MicroMsg.SDK.WXApiImplV10", "open wx app failed, not installed or signature check failed");
            return 0;
        }
        return new MMSharedPreferences(this.context).getInt("_build_info_sdk_int_", 0);
    }

    public final boolean handleIntent(Intent paramIntent, IWXAPIEventHandler paramIWXAPIEventHandler) {
        if (!WXApiImplComm.isIntentFromWx(paramIntent, "com.tencent.mm.openapi.token")) {
            com.tencent.mm.sdk.b.a.b("MicroMsg.SDK.WXApiImplV10", "handleIntent fail, intent not from weixin msg");
            return false;
        }
        if (this.detached)
            throw new IllegalStateException("handleIntent fail, WXMsgImpl has been detached");
        String str1 = paramIntent.getStringExtra("_mmessage_content");
        int i = paramIntent.getIntExtra("_mmessage_sdkVersion", 0);
        String str2 = paramIntent.getStringExtra("_mmessage_appPackage");
        if ((str2 == null) || (str2.length() == 0)) {
            com.tencent.mm.sdk.b.a.a("MicroMsg.SDK.WXApiImplV10", "invalid argument");
            return false;
        }
        if (!checkSumConsistent(paramIntent.getByteArrayExtra("_mmessage_checksum"), b.a(str1, i, str2))) {
            com.tencent.mm.sdk.b.a.a("MicroMsg.SDK.WXApiImplV10", "checksum fail");
            return false;
        }
        int j = paramIntent.getIntExtra("_wxapi_command_type", 0);
        switch(j) {
            case 7:
            case 8:
            default:
                com.tencent.mm.sdk.b.a.a("MicroMsg.SDK.WXApiImplV10", "unknown cmd = " + j);
                return false;
            case 1:
                paramIWXAPIEventHandler.onResp(new SendAuth.Resp(paramIntent.getExtras()));
                return true;
            case 2:
                paramIWXAPIEventHandler.onResp(new SendMessageToWX.Resp(paramIntent.getExtras()));
                return true;
            case 3:
                paramIWXAPIEventHandler.onReq(new GetMessageFromWX.Req(paramIntent.getExtras()));
                return true;
            case 4:
                paramIWXAPIEventHandler.onReq(new ShowMessageFromWX.Req(paramIntent.getExtras()));
                return true;
            case 5:
                paramIWXAPIEventHandler.onResp(new PayResp(paramIntent.getExtras()));
                return true;
            case 6:
                paramIWXAPIEventHandler.onReq(new LaunchFromWX.Req(paramIntent.getExtras()));
                return true;
            case 9:
        }
        paramIWXAPIEventHandler.onResp(new AddCardToWXCardPackage.Resp(paramIntent.getExtras()));
        return true;
    }

    public final boolean isWXAppInstalled() {
        if (this.detached)
            throw new IllegalStateException("isWXAppInstalled fail, WXMsgImpl has been detached");

        return false;
    }

    public final boolean isWXAppSupportAPI() {
        if (this.detached)
            throw new IllegalStateException("isWXAppSupportAPI fail, WXMsgImpl has been detached");
        return getWXAppSupportAPI() >= 570490883;
    }

    public final boolean openWXApp() {
        if (this.detached)
            throw new IllegalStateException("openWXApp fail, WXMsgImpl has been detached");
        if (!isWXAppInstalled()) {
            com.tencent.mm.sdk.b.a.a("MicroMsg.SDK.WXApiImplV10", "open wx app failed, not installed or signature check failed");
            return false;
        }
        try {
            this.context.startActivity(this.context.getPackageManager().getLaunchIntentForPackage("com.tencent.mm"));
            return true;
        } catch (Exception localException) {
            com.tencent.mm.sdk.b.a.a("MicroMsg.SDK.WXApiImplV10", "startActivity fail, exception = " + localException.getMessage());
        }
        return false;
    }

    public final boolean registerApp(String paramString) {
        if (this.detached)
            throw new IllegalStateException("registerApp fail, WXMsgImpl has been detached");
        if (!WXApiImplComm.validateAppSignatureForPackage(this.context, "com.tencent.mm", this.checkSignature)) {
            com.tencent.mm.sdk.b.a.a("MicroMsg.SDK.WXApiImplV10", "register app failed for wechat app signature check failed");
            return false;
        }
        com.tencent.mm.sdk.b.a.c("MicroMsg.SDK.WXApiImplV10", "registerApp, appId = " + paramString);
        if (paramString != null)
            this.appId = paramString;
        com.tencent.mm.sdk.b.a.c("MicroMsg.SDK.WXApiImplV10", "register app " + this.context.getPackageName());
        com.tencent.mm.sdk.a.a.a.a locala = new com.tencent.mm.sdk.a.a.a.a();
        locala.f = "com.tencent.mm";
        locala.g = "com.tencent.mm.plugin.openapi.Intent.ACTION_HANDLE_APP_REGISTER";
        locala.d = ("weixin://registerapp?appid=" + this.appId);
        return com.tencent.mm.sdk.a.a.a.a(this.context, locala);
    }

    public final boolean sendReq(BaseReq paramBaseReq) {
        if (this.detached)
            throw new IllegalStateException("sendReq fail, WXMsgImpl has been detached");
        if (!WXApiImplComm.validateAppSignatureForPackage(this.context, "com.tencent.mm", this.checkSignature)) {
            com.tencent.mm.sdk.b.a.a("MicroMsg.SDK.WXApiImplV10", "sendReq failed for wechat app signature check failed");
            return false;
        }
        if (!paramBaseReq.checkArgs()) {
            com.tencent.mm.sdk.b.a.a("MicroMsg.SDK.WXApiImplV10", "sendReq checkArgs fail");
            return false;
        }
        com.tencent.mm.sdk.b.a.c("MicroMsg.SDK.WXApiImplV10", "sendReq, req type = " + paramBaseReq.getType());
        Bundle localBundle = new Bundle();
        paramBaseReq.toBundle(localBundle);
        if (paramBaseReq.getType() == 5)
            return sendPayReq(this.context, localBundle);
        if (paramBaseReq.getType() == 7)
            return sendJumpToBizProfileReq(this.context, localBundle);
        if (paramBaseReq.getType() == 8)
            return sendJumpToBizWebviewReq(this.context, localBundle);
        if (paramBaseReq.getType() == 9)
            return sendAddCardToWX(this.context, localBundle);
        com.tencent.mm.sdk.a.a.a locala = new com.tencent.mm.sdk.a.a.a();
        locala.e = localBundle;
        locala.d = ("weixin://sendreq?appid=" + this.appId);
        locala.b = "com.tencent.mm";
        locala.c = "com.tencent.mm.plugin.base.stub.WXEntryActivity";
        return com.tencent.mm.sdk.a.a.a(this.context, locala);
    }

    public final boolean sendResp(BaseResp paramBaseResp) {
        if (this.detached)
            throw new IllegalStateException("sendResp fail, WXMsgImpl has been detached");
        if (!WXApiImplComm.validateAppSignatureForPackage(this.context, "com.tencent.mm", this.checkSignature)) {
            com.tencent.mm.sdk.b.a.a("MicroMsg.SDK.WXApiImplV10", "sendResp failed for wechat app signature check failed");
            return false;
        }
        if (!paramBaseResp.checkArgs()) {
            com.tencent.mm.sdk.b.a.a("MicroMsg.SDK.WXApiImplV10", "sendResp checkArgs fail");
            return false;
        }
        Bundle localBundle = new Bundle();
        paramBaseResp.toBundle(localBundle);
        com.tencent.mm.sdk.a.a.a locala = new com.tencent.mm.sdk.a.a.a();
        locala.e = localBundle;
        locala.d = ("weixin://sendresp?appid=" + this.appId);
        locala.b = "com.tencent.mm";
        locala.c = "com.tencent.mm.plugin.base.stub.WXEntryActivity";
        return com.tencent.mm.sdk.a.a.a(this.context, locala);
    }

    public final void unregisterApp() {
        if (this.detached)
            throw new IllegalStateException("unregisterApp fail, WXMsgImpl has been detached");
        if (!WXApiImplComm.validateAppSignatureForPackage(this.context, "com.tencent.mm", this.checkSignature)) {
            com.tencent.mm.sdk.b.a.a("MicroMsg.SDK.WXApiImplV10", "unregister app failed for wechat app signature check failed");
            return;
        }
        com.tencent.mm.sdk.b.a.c("MicroMsg.SDK.WXApiImplV10", "unregisterApp, appId = " + this.appId);
        if ((this.appId == null) || (this.appId.length() == 0)) {
            com.tencent.mm.sdk.b.a.a("MicroMsg.SDK.WXApiImplV10", "unregisterApp fail, appId is empty");
            return;
        }
        com.tencent.mm.sdk.b.a.c("MicroMsg.SDK.WXApiImplV10", "unregister app " + this.context.getPackageName());
        com.tencent.mm.sdk.a.a.a.a locala = new com.tencent.mm.sdk.a.a.a.a();
        locala.f = "com.tencent.mm";
        locala.g = "com.tencent.mm.plugin.openapi.Intent.ACTION_HANDLE_APP_UNREGISTER";
        locala.d = ("weixin://unregisterapp?appid=" + this.appId);
        com.tencent.mm.sdk.a.a.a.a(this.context, locala);
    }
}


@Override
    @SuppressWarnings("unchecked")
    public List<T> getList()

// Oracle - initial API and implementation
package org.eclipse.persistence.jpa.jpql.tools.model;

import java.util.List;
import org.eclipse.persistence.jpa.jpql.tools.model.query.ListHolderStateObject;
import org.eclipse.persistence.jpa.jpql.tools.model.query.StateObject;
import org.eclipse.persistence.jpa.jpql.utility.iterable.ListIterable;
import org.eclipse.persistence.jpa.jpql.utility.iterable.SnapshotCloneListIterable;

/**
 * The default implementation of {@link IListChangeListener} where the generics is the type of the
 * items.
 *
 * @version 2.4
 * @since 2.4
 * @author Pascal Filion
 */
public class ListChangeEvent<T> implements IListChangeEvent<T> {

    private int endIndex;

    private EventType eventType;

    private List<? extends T> items;

    private List<? extends T> list;

    private String listName;

    /**
     * The source where the modification occurred and that fired the event.
     */
    private StateObject source;

    private int startIndex;

    /**
     * Creates a new ListChangeEvent.
     *
     * @param source The source where the modification occurred and that fired the event
     */
    public ListChangeEvent(StateObject source, List<? extends T> list, EventType eventType, String listName, List<? extends T> items, int startIndex, int endIndex) {
        super();
        this.list = list;
        this.items = items;
        this.source = source;
        this.endIndex = endIndex;
        this.listName = listName;
        this.eventType = eventType;
        this.startIndex = startIndex;
    }

    @Override
    public int getEndIndex() {
        return endIndex;
    }

    @Override
    public EventType getEventType() {
        return eventType;
    }

{
        return (List<T>) list;
    }

    @Override
    public String getListName() {
        return listName;
    }

    @Override
    @SuppressWarnings("unchecked")
    public <S extends ListHolderStateObject<? extends T>> S getSource() {
        return (S) source;
    }

    @Override
    public int getStartIndex() {
        return startIndex;
    }

    @Override
    public ListIterable<T> items() {
        return new SnapshotCloneListIterable<>(items);
    }

    @Override
    public int itemsSize() {
        return items.size();
    }
}


// Oracle - initial API and implementation
package org.eclipse.persistence.jpa.jpql.tools.model;

import java.util.List;
import org.eclipse.persistence.jpa.jpql.tools.model.query.ListHolderStateObject;
import org.eclipse.persistence.jpa.jpql.tools.model.query.StateObject;
import org.eclipse.persistence.jpa.jpql.utility.iterable.ListIterable;
import org.eclipse.persistence.jpa.jpql.utility.iterable.SnapshotCloneListIterable;

/**
 * The default implementation of {@link IListChangeListener} where the generics is the type of the
 * items.
 *
 * @version 2.4
 * @since 2.4
 * @author Pascal Filion
 */
public class ListChangeEvent<T> implements IListChangeEvent<T> {

    private int endIndex;

    private EventType eventType;

    private List<? extends T> items;

    private List<? extends T> list;

    private String listName;

    /**
     * The source where the modification occurred and that fired the event.
     */
    private StateObject source;

    private int startIndex;

    /**
     * Creates a new ListChangeEvent.
     *
     * @param source The source where the modification occurred and that fired the event
     */
    public ListChangeEvent(StateObject source, List<? extends T> list, EventType eventType, String listName, List<? extends T> items, int startIndex, int endIndex) {
        super();
        this.list = list;
        this.items = items;
        this.source = source;
        this.endIndex = endIndex;
        this.listName = listName;
        this.eventType = eventType;
        this.startIndex = startIndex;
    }

    @Override
    public int getEndIndex()

    @Override
    public EventType getEventType() {
        return eventType;
    }

    @Override
    @SuppressWarnings("unchecked")
    public List<T> getList() {
        return (List<T>) list;
    }

    @Override
    public String getListName() {
        return listName;
    }

    @Override
    @SuppressWarnings("unchecked")
    public <S extends ListHolderStateObject<? extends T>> S getSource() {
        return (S) source;
    }

    @Override
    public int getStartIndex() {
        return startIndex;
    }

    @Override
    public ListIterable<T> items() {
        return new SnapshotCloneListIterable<>(items);
    }

    @Override
    public int itemsSize() {
        return items.size();
    }
}


// Oracle - initial API and implementation
package org.eclipse.persistence.jpa.jpql.tools.model;

import java.util.List;
import org.eclipse.persistence.jpa.jpql.tools.model.query.ListHolderStateObject;
import org.eclipse.persistence.jpa.jpql.tools.model.query.StateObject;
import org.eclipse.persistence.jpa.jpql.utility.iterable.ListIterable;
import org.eclipse.persistence.jpa.jpql.utility.iterable.SnapshotCloneListIterable;

/**
 * The default implementation of {@link IListChangeListener} where the generics is the type of the
 * items.
 *
 * @version 2.4
 * @since 2.4
 * @author Pascal Filion
 */
public class ListChangeEvent<T> implements IListChangeEvent<T> {

    private int endIndex;

    private EventType eventType;

    private List<? extends T> items;

    private List<? extends T> list;

    private String listName;

    /**
     * The source where the modification occurred and that fired the event.
     */
    private StateObject source;

    private int startIndex;

    /**
     * Creates a new ListChangeEvent.
     *
     * @param source The source where the modification occurred and that fired the event
     */
    public ListChangeEvent(StateObject source, List<? extends T> list, EventType eventType, String listName, List<? extends T> items, int startIndex, int endIndex) {
        super();
        this.list = list;
        this.items = items;
        this.source = source;
        this.endIndex = endIndex;
        this.listName = listName;
        this.eventType = eventType;
        this.startIndex = startIndex;
    }

    @Override
    public int getEndIndex() {
        return endIndex;
    }

    @Override
    public EventType getEventType() {
        return eventType;
    }

    @Override
    @SuppressWarnings("unchecked")
    public List<T> getList() {
        return (List<T>) list;
    }

    @Override
    public String getListName() {
        return lis

    }

    @Override
    @SuppressWarnings("unchecked")
    public <S extends ListHolderStateObject<? extends T>> S getSource() {
        return (S) source;
    }

    @Override
    public int getStartIndex() {
        return startIndex;
    }

    @Override
    public ListIterable<T> items() {
        return new SnapshotCloneListIterable<>(items);
    }

    @Override
    public int itemsSize() {
        return items.size();
    }
}


public static Spannable getResourcesText(Resources res, @StringRes int resId, Object... args)

package com.android.settings.datetime.timezone;

import android.annotation.StringRes;
import android.content.res.Resources;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import java.util.Formatter;
import java.util.Locale;

public class SpannableUtil {

    /**
     * {@class Resources} has no method to format string resource with {@class Spannable} a
     * rguments. It's a helper method for this purpose.
     */

{
        final Locale locale = res.getConfiguration().getLocales().get(0);
        final SpannableStringBuilder builder = new SpannableStringBuilder();
        new Formatter(builder, locale).format(res.getString(resId), args);
        return builder;
    }
}


{
        final Locale locale = res.getConfiguration().getLocales().get(0);
        final SpannableStringBuilder builder = new SpannableStringBuilder();
        new Formatter(builder, locale).format(res.getString(resId), args);
        return builder;
    }

package com.android.settings.datetime.timezone;

import android.annotation.StringRes;
import android.content.res.Resources;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import java.util.Formatter;
import java.util.Locale;

public class SpannableUtil {

    /**
     * {@class Resources} has no method to format string resource with {@class Spannable} a
     * rguments. It's a helper method for this purpose.
     */
    public static Spannable getResourcesText(Resources res, @StringRes int resId, Object... args)


package com.android.settings.datetime.timezone;

import android.annotation.StringRes;
import android.content.res.Resources;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import java.util.Formatter;
import java.util.Locale;

public class SpannableUtil {

    /**
     * {@class Resources} has no method to format string resource with {@class Spannable} a
     * rguments. It's a helper method for this purpose.
     */
    public static Spannable getResourcesText(Resources res, @StringRes int resId, Object... args) {
        final Locale locale = res.getConfiguration().getLocales().get(0);
        final SpannableStringBuilder builder = new SpannableStringBuilder();
        new Formatter(builder, locale).format(res.getString(resId), args);
        return bu


public static Spannable getResourcesText(Resources res, @StringRes int resId, Object... args) {
        final Locale locale = res.getConfiguration().getLocales().get(0);
        final SpannableStringBuilder builder = new SpannableStringBuilder();
        new Formatter(builder, locale).format(res.getString(resId), args);
        return builder;
    }


@Override
    public void close() throws IOException

package com.facebook.buck.jvm.java;

import com.google.common.base.Charsets;
import com.google.common.io.CharStreams;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import javax.annotation.Nullable;
import javax.annotation.concurrent.GuardedBy;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;

class ZipEntryJavaFileObject extends SimpleJavaFileObject implements Closeable {

    private final ZipFile zipFile;

    private final ZipEntry zipEntry;

    @GuardedBy("this")
    @Nullable
    private String contents;

    public ZipEntryJavaFileObject(ZipFile zipFile, ZipEntry zipEntry) {
        super(createURIFromEntry(zipEntry), JavaFileObject.Kind.SOURCE);
        this.zipFile = zipFile;
        this.zipEntry = zipEntry;
    }

    /**
     * Creates a canonical URI that represents the {@link ZipEntry}. This URI starts with {@code
     * "string:///"} because {@link JavaCompiler} does not seem to tolerate URIs that start with
     * {@code "jar:///"}, even though that would be more appropriate.
     */
    private static URI createURIFromEntry(ZipEntry entry) {
        try {
            return new URI("string:///" + entry.getName());
        } catch (URISyntaxException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * Returns the contents of the {@link ZipEntry} as a string. Ensures that the entry is read at
     * most once.
     */
    private synchronized String getContentsAsString() {
        if (contents != null) {
            return contents;
        }
        try (InputStream inputStream = zipFile.getInputStream(zipEntry);
            InputStreamReader isr = new InputStreamReader(inputStream, Charsets.UTF_8)) {
            contents = CharStreams.toString(isr);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return contents;
    }

    /**
     * Closes the {@link ZipFile} this entry was loaded from. Use with care.
     */

{
        zipFile.close();
    }

    @Override
    public CharSequence getCharContent(boolean ignoreEncodingErrors) {
        return getContentsAsString();
    }
}


{
        try {
            return new URI("string:///" + entry.getName());
        } catch (URISyntaxException e) {
            throw new RuntimeException(e);
        }
    }

package com.facebook.buck.jvm.java;

import com.google.common.base.Charsets;
import com.google.common.io.CharStreams;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import javax.annotation.Nullable;
import javax.annotation.concurrent.GuardedBy;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;

class ZipEntryJavaFileObject extends SimpleJavaFileObject implements Closeable {

    private final ZipFile zipFile;

    private final ZipEntry zipEntry;

    @GuardedBy("this")
    @Nullable
    private String contents;

    public ZipEntryJavaFileObject(ZipFile zipFile, ZipEntry zipEntry) {
        super(createURIFromEntry(zipEntry), JavaFileObject.Kind.SOURCE);
        this.zipFile = zipFile;
        this.zipEntry = zipEntry;
    }

    /**
     * Creates a canonical URI that represents the {@link ZipEntry}. This URI starts with {@code
     * "string:///"} because {@link JavaCompiler} does not seem to tolerate URIs that start with
     * {@code "jar:///"}, even though that would be more appropriate.
     */
    private static URI createURIFromEntry(ZipEntry entry)

    /**
     * Returns the contents of the {@link ZipEntry} as a string. Ensures that the entry is read at
     * most once.
     */
    private synchronized String getContentsAsString() {
        if (contents != null) {
            return contents;
        }
        try (InputStream inputStream = zipFile.getInputStream(zipEntry);
            InputStreamReader isr = new InputStreamReader(inputStream, Charsets.UTF_8)) {
            contents = CharStreams.toString(isr);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return contents;
    }

    /**
     * Closes the {@link ZipFile} this entry was loaded from. Use with care.
     */
    @Override
    public void close() throws IOException {
        zipFile.close();
    }

    @Override
    public CharSequence getCharContent(boolean ignoreEncodingErrors) {
        return getContentsAsString();
    }
}


package com.facebook.buck.jvm.java;

import com.google.common.base.Charsets;
import com.google.common.io.CharStreams;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import javax.annotation.Nullable;
import javax.annotation.concurrent.GuardedBy;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;

class ZipEntryJavaFileObject extends SimpleJavaFileObject implements Closeable {

    private final ZipFile zipFile;

    private final ZipEntry zipEntry;

    @GuardedBy("this")
    @Nullable
    private String contents;

    public ZipEntryJavaFileObject(ZipFile zipFile, ZipEntry zipEntry) {
        super(createURIFromEntry(zipEntry), JavaFileObject.Kind.SOURCE);
        this.zipFile = zipFile;
        this.zipEntry = zipEntry;
    }

    /**
     * Creates a canonical URI that represents the {@link ZipEntry}. This URI starts with {@code
     * "string:///"} because {@link JavaCompiler} does not seem to tolerate URIs that start with
     * {@code "jar:///"}, even though that would be more appropriate.
     */
    private static URI createURIFromEntry(ZipEntry entry) {
        try {
            return new URI("string:///" + entry.getName());
        } catch (URISyntaxException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * Returns the contents of the {@link ZipEntry} as a string. Ensures that the entry is read at
     * most once.
     */
    private synchronized String getContentsAsString() {
        if (contents != null) {
            return contents;
        }
        try (InputStream inputStream = zipFile.getInputStream(zipEntry);
            InputStreamReader isr = new InputStreamReader(inputStream, Charsets.UTF_8)) {
            contents = CharStreams.toString(isr);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return c

    }

    /**
     * Closes the {@link ZipFile} this entry was loaded from. Use with care.
     */
    @Override
    public void close() throws IOException {
        zipFile.close();
    }

    @Override
    public CharSequence getCharContent(boolean ignoreEncodingErrors) {
        return getContentsAsString();
    }
}


private static URI createURIFromEntry(ZipEntry entry) {
        try {
            return new URI("string:///" + entry.getName());
        } catch (URISyntaxException e) {
            throw new RuntimeException(e);
        }
    }

package com.facebook.buck.jvm.java;

import com.google.common.base.Charsets;
import com.google.common.io.CharStreams;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import javax.annotation.Nullable;
import javax.annotation.concurrent.GuardedBy;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;

class ZipEntryJavaFileObject extends SimpleJavaFileObject implements Closeable {

    private final ZipFile zipFile;

    private final ZipEntry zipEntry;

    @GuardedBy("this")
    @Nullable
    private String contents;

    public ZipEntryJavaFileObject(ZipFile zipFile, ZipEntry zipEntry) {
        super(createURIFromEntry(zipEntry), JavaFileObject.Kind.SOURCE);
        this.zipFile = zipFile;
        this.zipEntry = zipEntry;
    }

    /**
     * Creates a canonical URI that represents the {@link ZipEntry}. This URI starts with {@code
     * "string:///"} because {@link JavaCompiler} does not seem to tolerate URIs that start with
     * {@code "jar:///"}, even though that would be more appropriate.
     */


try {
            return new URI("string:///" + entry.getName());
        } catch (URISyntaxException e) {
            throw new RuntimeException(e);
        }

package com.facebook.buck.jvm.java;

import com.google.common.base.Charsets;
import com.google.common.io.CharStreams;
import java.io.Closeable;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import javax.annotation.Nullable;
import javax.annotation.concurrent.GuardedBy;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.SimpleJavaFileObject;

class ZipEntryJavaFileObject extends SimpleJavaFileObject implements Closeable {

    private final ZipFile zipFile;

    private final ZipEntry zipEntry;

    @GuardedBy("this")
    @Nullable
    private String contents;

    public ZipEntryJavaFileObject(ZipFile zipFile, ZipEntry zipEntry) {
        super(createURIFromEntry(zipEntry), JavaFileObject.Kind.SOURCE);
        this.zipFile = zipFile;
        this.zipEntry = zipEntry;
    }

    /**
     * Creates a canonical URI that represents the {@link ZipEntry}. This URI starts with {@code
     * "string:///"} because {@link JavaCompiler} does not seem to tolerate URIs that start with
     * {@code "jar:///"}, even though that would be more appropriate.
     */
    private static URI createURIFromEntry(ZipEntry entry) {

    }

    /**
     * Returns the contents of the {@link ZipEntry} as a string. Ensures that the entry is read at
     * most once.
     */
    private synchronized String getContentsAsString() {
        if (contents != null) {
            return contents;
        }
        try (InputStream inputStream = zipFile.getInputStream(zipEntry);
            InputStreamReader isr = new InputStreamReader(inputStream, Charsets.UTF_8)) {
            contents = CharStreams.toString(isr);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return contents;
    }

    /**
     * Closes the {@link ZipFile} this entry was loaded from. Use with care.
     */
    @Override
    public void close() throws IOException {
        zipFile.close();
    }

    @Override
    public CharSequence getCharContent(boolean ignoreEncodingErrors) {
        return getContentsAsString();
    }
}


package android.databinding.tool.reflection;

import android.databinding.tool.reflection.Callable.Type;
import android.databinding.tool.util.L;
import android.databinding.tool.util.StringUtils;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static android.databinding.tool.reflection.Callable.CAN_BE_INVALIDATED;
import static android.databinding.tool.reflection.Callable.DYNAMIC;
import static android.databinding.tool.reflection.Callable.STATIC;

public abstract class ModelClass {

    public abstract String toJavaCode();

    /**
     * @return whether this ModelClass represents an array.
     */
    public abstract boolean isArray();

    /**
     * For arrays, lists, and maps, this returns the contained value. For other types, null
     * is returned.
     *
     * @return The component type for arrays, the value type for maps, and the element type
     * for lists.
     */
    public abstract ModelClass getComponentType();

    /**
     * @return Whether or not this ModelClass can be treated as a List. This means
     * it is a java.util.List, or one of the Sparse*Array classes.
     */
    public boolean isList() {
        for (ModelClass listType : ModelAnalyzer.getInstance().getListTypes()) {
            if (listType != null) {
                if (listType.isAssignableFrom(this)) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * @return whether or not this ModelClass can be considered a Map or not.
     */
    public boolean isMap() {
        return ModelAnalyzer.getInstance().getMapType().isAssignableFrom(erasure());
    }

    /**
     * @return whether or not this ModelClass is a java.lang.String.
     */
    public boolean isString() {
        return ModelAnalyzer.getInstance().getStringType().equals(this);
    }

    /**
     * @return whether or not this ModelClass represents a Reference type.
     */
    public abstract boolean isNullable();

    /**
     * @return whether or not this ModelClass represents a primitive type.
     */
    public abstract boolean isPrimitive();

    /**
     * @return whether or not this ModelClass represents a Java boolean
     */
    public abstract boolean isBoolean();

    /**
     * @return whether or not this ModelClass represents a Java char
     */
    public abstract boolean isChar();

    /**
     * @return whether or not this ModelClass represents a Java byte
     */
    public abstract boolean isByte();

    /**
     * @return whether or not this ModelClass represents a Java short
     */
    public abstract boolean isShort();

    /**
     * @return whether or not this ModelClass represents a Java int
     */
    public abstract boolean isInt();

    /**
     * @return whether or not this ModelClass represents a Java long
     */
    public abstract boolean isLong();

    /**
     * @return whether or not this ModelClass represents a Java float
     */
    public abstract boolean isFloat();

    /**
     * @return whether or not this ModelClass represents a Java double
     */
    public abstract boolean isDouble();

    /**
     * @return whether or not this has type parameters
     */
    public abstract boolean isGeneric();

    /**
     * @return a list of Generic type paramters for the class. For example, if the class
     * is List<T>, then the return value will be a list containing T. null is returned
     * if this is not a generic type
     */
    public abstract List<ModelClass> getTypeArguments();

    /**
     * @return whether this is a type variable. For example, in List<T>, T is a type variable.
     * However, List<String>, String is not a type variable.
     */
    public abstract boolean isTypeVar();

    /**
     * @return whether this is a wildcard type argument or not.
     */
    public abstract boolean isWildcard();

    /**
     * @return whether or not this ModelClass is java.lang.Object and not a primitive or subclass.
     */
    public boolean isObject() {
        return ModelAnalyzer.getInstance().getObjectType().equals(this);
    }

    /**
     * @return whether or not this ModelClass is an interface
     */
    public abstract boolean isInterface();

    /**
     * @return whether or not his is a ViewDataBinding subclass.
     */
    public boolean isViewDataBinding() {
        return ModelAnalyzer.getInstance().getViewDataBindingType().isAssignableFrom(this);
    }

    /**
     * @return whether or not this ModelClass type extends ViewStub.
     */
    public boolean extendsViewStub() {
        return ModelAnalyzer.getInstance().getViewStubType().isAssignableFrom(this);
    }

    /**
     * @return whether or not this is an Observable type such as ObservableMap, ObservableList,
     * or Observable.
     */
    public boolean isObservable() {
        ModelAnalyzer modelAnalyzer = ModelAnalyzer.getInstance();
        return modelAnalyzer.getObservableType().isAssignableFrom(this) || modelAnalyzer.getObservableListType().isAssignableFrom(this) || modelAnalyzer.getObservableMapType().isAssignableFrom(this);
    }

    /**
     * @return whether or not this is an ObservableField, or any of the primitive versions
     * such as ObservableBoolean and ObservableInt
     */
    public boolean isObservableField() {
        ModelClass erasure = erasure();
        for (ModelClass observableField : ModelAnalyzer.getInstance().getObservableFieldTypes()) {
            if (observableField.isAssignableFrom(erasure)) {
                return true;
            }
        }
        return false;
    }

    /**
     * @return whether or not this ModelClass represents a void
     */
    public abstract boolean isVoid();

    /**
     * When this is a boxed type, such as Integer, this will return the unboxed value,
     * such as int. If this is not a boxed type, this is returned.
     *
     * @return The unboxed type of the class that this ModelClass represents or this if it isn't a
     * boxed type.
     */
    public abstract ModelClass unbox();

    /**
     * When this is a primitive type, such as boolean, this will return the boxed value,
     * such as Boolean. If this is not a primitive type, this is returned.
     *
     * @return The boxed type of the class that this ModelClass represents or this if it isn't a
     * primitive type.
     */
    public abstract ModelClass box();

    /**
     * Returns whether or not the type associated with that can be assigned to
     * the type associated with this ModelClass. If this and that only require boxing or unboxing
     * then true is returned.
     *
     * @param that the ModelClass to compare.
     * @return true if that requires only boxing or if that is an
     * implementation of or subclass of this.
     */
    public abstract boolean isAssignableFrom(ModelClass that);

    /**
     * Returns an array containing all public methods (or protected if allowProtected is true)
     * on the type represented by this ModelClass with the name name and can
     * take the passed-in types as arguments. This will also work if the arguments match
     * VarArgs parameter.
     *
     * @param name The name of the method to find.
     * @param args The types that the method should accept.
     * @param staticOnly Whether only static methods should be returned or both instance methods
     *                 and static methods are valid.
     * @param allowProtected true if the method can be protected as well as public.
     *
     * @return An array containing all public methods with the name name and taking
     * args parameters.
     */
    public ModelMethod[] getMethods(String name, List<ModelClass> args, boolean staticOnly, boolean allowProtected) {
        ModelMethod[] methods = getDeclaredMethods();
        ArrayList<ModelMethod> matching = new ArrayList<ModelMethod>();
        for (ModelMethod method : methods) {
            if ((method.isPublic() || (allowProtected && method.isProtected())) && (!staticOnly || method.isStatic()) && name.equals(method.getName()) && method.acceptsArguments(args)) {
                matching.add(method);
            }
        }
        return matching.toArray(new ModelMethod[matching.size()]);
    }

    /**
     * Returns all public instance methods with the given name and number of parameters.
     *
     * @param name The name of the method to find.
     * @param numParameters The number of parameters that the method should take
     * @return An array containing all public methods with the given name and number of parameters.
     */
    public ModelMethod[] getMethods(String name, int numParameters) {
        ModelMethod[] methods = getDeclaredMethods();
        ArrayList<ModelMethod> matching = new ArrayList<ModelMethod>();
        for (ModelMethod method : methods) {
            if (method.isPublic() && !method.isStatic() && name.equals(method.getName()) && method.getParameterTypes().length == numParameters) {
                matching.add(method);
            }
        }
        return matching.toArray(new ModelMethod[matching.size()]);
    }

    /**
     * Returns the public method with the name name with the parameters that
     * best match args. staticOnly governs whether a static or instance method
     * will be returned. If no matching method was found, null is returned.
     *
     * @param name The method name to find
     * @param args The arguments that the method should accept
     * @param staticOnly true if the returned method must be static or false if it does not
     *                     matter.
     * @param allowProtected true if the method can be protected as well as public.
     */
    public ModelMethod getMethod(String name, List<ModelClass> args, boolean staticOnly, boolean allowProtected) {
        ModelMethod[] methods = getMethods(name, args, staticOnly, allowProtected);
        L.d("looking methods for %s. static only ? %s . method count: %d", name, staticOnly, methods.length);
        for (ModelMethod method : methods) {
            L.d("method: %s, %s", method.getName(), method.isStatic());
        }
        if (methods.length == 0) {
            return null;
        }
        ModelMethod bestMethod = methods[0];
        for (int i = 1; i < methods.length; i++) {
            if (methods[i].isBetterArgMatchThan(bestMethod, args)) {
                bestMethod = methods[i];
            }
        }
        return bestMethod;
    }

    /**
     * If this represents a class, the super class that it extends is returned. If this
     * represents an interface, the interface that this extends is returned.
     * null is returned if this is not a class or interface, such as an int, or
     * if it is java.lang.Object or an interface that does not extend any other type.
     *
     * @return The class or interface that this ModelClass extends or null.
     */
    public abstract ModelClass getSuperclass();

    /**
     * @return A String representation of the class or interface that this represents, not
     * including any type arguments.
     */

{
        return erasure().toJavaCode();
    }

    /**
     * @return The class or interface name of this type or the primitive type if it isn't a
     * reference type.
     */
    public String getSimpleName() {
        final String canonicalName = getCanonicalName();
        final int dotIndex = canonicalName.lastIndexOf('.');
        if (dotIndex >= 0) {
            return canonicalName.substring(dotIndex + 1);
        }
        return canonicalName;
    }

    /**
     * Returns this class type without any generic type arguments.
     * @return this class type without any generic type arguments.
     */
    public abstract ModelClass erasure();

    /**
     * Since when this class is available. Important for Binding expressions so that we don't
     * call non-existing APIs when setting UI.
     *
     * @return The SDK_INT where this method was added. If it is not a framework method, should
     * return 1.
     */
    public int getMinApi() {
        return SdkUtil.getMinApi(this);
    }

    /**
     * Returns the JNI description of the method which can be used to lookup it in SDK.
     * @see TypeUtil
     */
    public abstract String getJniDescription();

    /**
     * Returns a list of all abstract methods in the type.
     */
    @NotNull
    public List<ModelMethod> getAbstractMethods() {
        ArrayList<ModelMethod> abstractMethods = new ArrayList<ModelMethod>();
        ModelMethod[] methods = getDeclaredMethods();
        for (ModelMethod method : methods) {
            if (method.isAbstract()) {
                abstractMethods.add(method);
            }
        }
        return abstractMethods;
    }

    /**
     * Returns the getter method or field that the name refers to.
     * @param name The name of the field or the body of the method name -- can be name(),
     *             getName(), or isName().
     * @param staticOnly Whether this should look for static methods and fields or instance
     *                     versions
     * @return the getter method or field that the name refers to or null if none can be found.
     */
    public Callable findGetterOrField(String name, boolean staticOnly) {
        if ("length".equals(name) && isArray()) {
            return new Callable(Type.FIELD, name, null, ModelAnalyzer.getInstance().loadPrimitive("int"), 0, 0, null);
        }
        String capitalized = StringUtils.capitalize(name);
        String[] methodNames = { "get" + capitalized, "is" + capitalized, name };
        for (String methodName : methodNames) {
            ModelMethod[] methods = getMethods(methodName, new ArrayList<ModelClass>(), staticOnly, false);
            for (ModelMethod method : methods) {
                if (method.isPublic() && (!staticOnly || method.isStatic()) && !method.getReturnType(Arrays.asList(method.getParameterTypes())).isVoid()) {
                    int flags = DYNAMIC;
                    if (method.isStatic()) {
                        flags |= STATIC;
                    }
                    if (method.isBindable()) {
                        flags |= CAN_BE_INVALIDATED;
                    } else {
                        // if method is not bindable, look for a backing field
                        final ModelField backingField = getField(name, true, method.isStatic());
                        L.d("backing field for method %s is %s", method.getName(), backingField == null ? "NOT FOUND" : backingField.getName());
                        if (backingField != null && backingField.isBindable()) {
                            flags |= CAN_BE_INVALIDATED;
                        }
                    }
                    final ModelMethod setterMethod = findSetter(method, name);
                    final String setterName = setterMethod == null ? null : setterMethod.getName();
                    final Callable result = new Callable(Callable.Type.METHOD, methodName, setterName, method.getReturnType(null), method.getParameterTypes().length, flags, method);
                    return result;
                }
            }
        }
        // could not find a method. Look for a public field
        ModelField publicField = null;
        if (staticOnly) {
            publicField = getField(name, false, true);
        } else {
            // first check non-static
            publicField = getField(name, false, false);
            if (publicField == null) {
                publicField = getField(name, false, true);
            }
        }
        if (publicField == null) {
            return null;
        }
        ModelClass fieldType = publicField.getFieldType();
        int flags = 0;
        String setterFieldName = name;
        if (publicField.isStatic()) {
            flags |= STATIC;
        }
        if (!publicField.isFinal()) {
            setterFieldName = null;
            flags |= DYNAMIC;
        }
        if (publicField.isBindable()) {
            flags |= CAN_BE_INVALIDATED;
        }
        return new Callable(Callable.Type.FIELD, name, setterFieldName, fieldType, 0, flags, null);
    }

    public ModelMethod findInstanceGetter(String name) {
        String capitalized = StringUtils.capitalize(name);
        String[] methodNames = { "get" + capitalized, "is" + capitalized, name };
        for (String methodName : methodNames) {
            ModelMethod[] methods = getMethods(methodName, new ArrayList<ModelClass>(), false, false);
            for (ModelMethod method : methods) {
                if (method.isPublic() && !method.isStatic() && !method.getReturnType(Arrays.asList(method.getParameterTypes())).isVoid()) {
                    return method;
                }
            }
        }
        return null;
    }

    private ModelField getField(String name, boolean allowPrivate, boolean isStatic) {
        ModelField[] fields = getDeclaredFields();
        for (ModelField field : fields) {
            boolean nameMatch = name.equals(field.getName()) || name.equals(stripFieldName(field.getName()));
            if (nameMatch && field.isStatic() == isStatic && (allowPrivate || field.isPublic())) {
                return field;
            }
        }
        return null;
    }

    private ModelMethod findSetter(ModelMethod getter, String originalName) {
        final String capitalized = StringUtils.capitalize(originalName);
        final String[] possibleNames;
        if (originalName.equals(getter.getName())) {
            possibleNames = new String[] { originalName, "set" + capitalized };
        } else if (getter.getName().startsWith("is")) {
            possibleNames = new String[] { "set" + capitalized, "setIs" + capitalized };
        } else {
            possibleNames = new String[] { "set" + capitalized };
        }
        for (String name : possibleNames) {
            List<ModelMethod> methods = findMethods(name, getter.isStatic());
            ModelClass param = getter.getReturnType(null);
            for (ModelMethod method : methods) {
                ModelClass[] parameterTypes = method.getParameterTypes();
                if (parameterTypes != null && parameterTypes.length == 1 && parameterTypes[0].equals(param) && method.isStatic() == getter.isStatic()) {
                    return method;
                }
            }
        }
        return null;
    }

    /**
     * Finds public methods that matches the given name exactly. These may be resolved into
     * listener methods during Expr.resolveListeners.
     */
    @NotNull
    public List<ModelMethod> findMethods(String name, boolean staticOnly) {
        ModelMethod[] methods = getDeclaredMethods();
        ArrayList<ModelMethod> matching = new ArrayList<ModelMethod>();
        for (ModelMethod method : methods) {
            if (method.getName().equals(name) && (!staticOnly || method.isStatic()) && method.isPublic()) {
                matching.add(method);
            }
        }
        return matching;
    }

    public boolean isIncomplete() {
        if (isTypeVar() || isWildcard()) {
            return true;
        }
        List<ModelClass> typeArgs = getTypeArguments();
        if (typeArgs != null) {
            for (ModelClass typeArg : typeArgs) {
                if (typeArg.isIncomplete()) {
                    return true;
                }
            }
        }
        return false;
    }

    protected abstract ModelField[] getDeclaredFields();

    protected abstract ModelMethod[] getDeclaredMethods();

    private static String stripFieldName(String fieldName) {
        // TODO: Make this configurable through IntelliJ
        if (fieldName.length() > 2) {
            final char start = fieldName.charAt(2);
            if (fieldName.startsWith("m_") && Character.isJavaIdentifierStart(start)) {
                return Character.toLowerCase(start) + fieldName.substring(3);
            }
        }
        if (fieldName.length() > 1) {
            final char start = fieldName.charAt(1);
            final char fieldIdentifier = fieldName.charAt(0);
            final boolean strip;
            if (fieldIdentifier == '_') {
                strip = true;
            } else if (fieldIdentifier == 'm' && Character.isJavaIdentifierStart(start) && !Character.isLowerCase(start)) {
                strip = true;
            } else {
                // not mUppercase format
                strip = false;
            }
            if (strip) {
                return Character.toLowerCase(start) + fieldName.substring(2);
            }
        }
        return fieldName;
    }
}