List of usage examples for java.lang CharSequence charAt
char charAt(int index);
From source file:org.apache.commons.lang3.StringUtils.java
/** * <p>Find the Levenshtein distance between two Strings if it's less than or equal to a given * threshold.</p>//from w w w . j a v a 2 s. co m * * <p>This is the number of changes needed to change one String into * another, where each change is a single character modification (deletion, * insertion or substitution).</p> * * <p>This implementation follows from Algorithms on Strings, Trees and Sequences by Dan Gusfield * and Chas Emerick's implementation of the Levenshtein distance algorithm from * <a href="http://www.merriampark.com/ld.htm">http://www.merriampark.com/ld.htm</a></p> * * <pre> * StringUtils.getLevenshteinDistance(null, *, *) = IllegalArgumentException * StringUtils.getLevenshteinDistance(*, null, *) = IllegalArgumentException * StringUtils.getLevenshteinDistance(*, *, -1) = IllegalArgumentException * StringUtils.getLevenshteinDistance("","", 0) = 0 * StringUtils.getLevenshteinDistance("aaapppp", "", 8) = 7 * StringUtils.getLevenshteinDistance("aaapppp", "", 7) = 7 * StringUtils.getLevenshteinDistance("aaapppp", "", 6)) = -1 * StringUtils.getLevenshteinDistance("elephant", "hippo", 7) = 7 * StringUtils.getLevenshteinDistance("elephant", "hippo", 6) = -1 * StringUtils.getLevenshteinDistance("hippo", "elephant", 7) = 7 * StringUtils.getLevenshteinDistance("hippo", "elephant", 6) = -1 * </pre> * * @param s the first String, must not be null * @param t the second String, must not be null * @param threshold the target threshold, must not be negative * @return result distance, or {@code -1} if the distance would be greater than the threshold * @throws IllegalArgumentException if either String input {@code null} or negative threshold */ public static int getLevenshteinDistance(CharSequence s, CharSequence t, int threshold) { if (s == null || t == null) { throw new IllegalArgumentException("Strings must not be null"); } if (threshold < 0) { throw new IllegalArgumentException("Threshold must not be negative"); } /* This implementation only computes the distance if it's less than or equal to the threshold value, returning -1 if it's greater. The advantage is performance: unbounded distance is O(nm), but a bound of k allows us to reduce it to O(km) time by only computing a diagonal stripe of width 2k + 1 of the cost table. It is also possible to use this to compute the unbounded Levenshtein distance by starting the threshold at 1 and doubling each time until the distance is found; this is O(dm), where d is the distance. One subtlety comes from needing to ignore entries on the border of our stripe eg. p[] = |#|#|#|* d[] = *|#|#|#| We must ignore the entry to the left of the leftmost member We must ignore the entry above the rightmost member Another subtlety comes from our stripe running off the matrix if the strings aren't of the same size. Since string s is always swapped to be the shorter of the two, the stripe will always run off to the upper right instead of the lower left of the matrix. As a concrete example, suppose s is of length 5, t is of length 7, and our threshold is 1. In this case we're going to walk a stripe of length 3. The matrix would look like so: 1 2 3 4 5 1 |#|#| | | | 2 |#|#|#| | | 3 | |#|#|#| | 4 | | |#|#|#| 5 | | | |#|#| 6 | | | | |#| 7 | | | | | | Note how the stripe leads off the table as there is no possible way to turn a string of length 5 into one of length 7 in edit distance of 1. Additionally, this implementation decreases memory usage by using two single-dimensional arrays and swapping them back and forth instead of allocating an entire n by m matrix. This requires a few minor changes, such as immediately returning when it's detected that the stripe has run off the matrix and initially filling the arrays with large values so that entries we don't compute are ignored. See Algorithms on Strings, Trees and Sequences by Dan Gusfield for some discussion. */ int n = s.length(); // length of s int m = t.length(); // length of t // if one string is empty, the edit distance is necessarily the length of the other if (n == 0) { return m <= threshold ? m : -1; } else if (m == 0) { return n <= threshold ? n : -1; } if (n > m) { // swap the two strings to consume less memory CharSequence tmp = s; s = t; t = tmp; n = m; m = t.length(); } int p[] = new int[n + 1]; // 'previous' cost array, horizontally int d[] = new int[n + 1]; // cost array, horizontally int _d[]; // placeholder to assist in swapping p and d // fill in starting table values int boundary = Math.min(n, threshold) + 1; for (int i = 0; i < boundary; i++) { p[i] = i; } // these fills ensure that the value above the rightmost entry of our // stripe will be ignored in following loop iterations Arrays.fill(p, boundary, p.length, Integer.MAX_VALUE); Arrays.fill(d, Integer.MAX_VALUE); // iterates through t for (int j = 1; j <= m; j++) { char t_j = t.charAt(j - 1); // jth character of t d[0] = j; // compute stripe indices, constrain to array size int min = Math.max(1, j - threshold); int max = Math.min(n, j + threshold); // the stripe may lead off of the table if s and t are of different sizes if (min > max) { return -1; } // ignore entry left of leftmost if (min > 1) { d[min - 1] = Integer.MAX_VALUE; } // iterates through [min, max] in s for (int i = min; i <= max; i++) { if (s.charAt(i - 1) == t_j) { // diagonally left and up d[i] = p[i - 1]; } else { // 1 + minimum of cell to the left, to the top, diagonally left and up d[i] = 1 + Math.min(Math.min(d[i - 1], p[i]), p[i - 1]); } } // copy current distance counts to 'previous row' distance counts _d = p; p = d; d = _d; } // if p[n] is greater than the threshold, there's no guarantee on it being the correct // distance if (p[n] <= threshold) { return p[n]; } else { return -1; } }
From source file:org.telegram.ui.PassportActivity.java
private void createAddressInterface(Context context) { languageMap = new HashMap<>(); try {/*from w w w .j av a 2s .c o m*/ BufferedReader reader = new BufferedReader( new InputStreamReader(context.getResources().getAssets().open("countries.txt"))); String line; while ((line = reader.readLine()) != null) { String[] args = line.split(";"); languageMap.put(args[1], args[2]); } reader.close(); } catch (Exception e) { FileLog.e(e); } topErrorCell = new TextInfoPrivacyCell(context); topErrorCell.setBackgroundDrawable( Theme.getThemedDrawable(context, R.drawable.greydivider_top, Theme.key_windowBackgroundGrayShadow)); topErrorCell.setPadding(0, AndroidUtilities.dp(7), 0, 0); linearLayout2.addView(topErrorCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); checkTopErrorCell(true); if (currentDocumentsType != null) { if (currentDocumentsType.type instanceof TLRPC.TL_secureValueTypeRentalAgreement) { actionBar.setTitle(LocaleController.getString("ActionBotDocumentRentalAgreement", R.string.ActionBotDocumentRentalAgreement)); } else if (currentDocumentsType.type instanceof TLRPC.TL_secureValueTypeBankStatement) { actionBar.setTitle(LocaleController.getString("ActionBotDocumentBankStatement", R.string.ActionBotDocumentBankStatement)); } else if (currentDocumentsType.type instanceof TLRPC.TL_secureValueTypeUtilityBill) { actionBar.setTitle(LocaleController.getString("ActionBotDocumentUtilityBill", R.string.ActionBotDocumentUtilityBill)); } else if (currentDocumentsType.type instanceof TLRPC.TL_secureValueTypePassportRegistration) { actionBar.setTitle(LocaleController.getString("ActionBotDocumentPassportRegistration", R.string.ActionBotDocumentPassportRegistration)); } else if (currentDocumentsType.type instanceof TLRPC.TL_secureValueTypeTemporaryRegistration) { actionBar.setTitle(LocaleController.getString("ActionBotDocumentTemporaryRegistration", R.string.ActionBotDocumentTemporaryRegistration)); } headerCell = new HeaderCell(context); headerCell.setText(LocaleController.getString("PassportDocuments", R.string.PassportDocuments)); headerCell.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); linearLayout2.addView(headerCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); documentsLayout = new LinearLayout(context); documentsLayout.setOrientation(LinearLayout.VERTICAL); linearLayout2.addView(documentsLayout, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); uploadDocumentCell = new TextSettingsCell(context); uploadDocumentCell.setBackgroundDrawable(Theme.getSelectorDrawable(true)); linearLayout2.addView(uploadDocumentCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); uploadDocumentCell.setOnClickListener(v -> { uploadingFileType = UPLOADING_TYPE_DOCUMENTS; openAttachMenu(); }); bottomCell = new TextInfoPrivacyCell(context); bottomCell.setBackgroundDrawable( Theme.getThemedDrawable(context, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow)); if (currentBotId != 0) { noAllDocumentsErrorText = LocaleController.getString("PassportAddAddressUploadInfo", R.string.PassportAddAddressUploadInfo); } else { if (currentDocumentsType.type instanceof TLRPC.TL_secureValueTypeRentalAgreement) { noAllDocumentsErrorText = LocaleController.getString("PassportAddAgreementInfo", R.string.PassportAddAgreementInfo); } else if (currentDocumentsType.type instanceof TLRPC.TL_secureValueTypeUtilityBill) { noAllDocumentsErrorText = LocaleController.getString("PassportAddBillInfo", R.string.PassportAddBillInfo); } else if (currentDocumentsType.type instanceof TLRPC.TL_secureValueTypePassportRegistration) { noAllDocumentsErrorText = LocaleController.getString("PassportAddPassportRegistrationInfo", R.string.PassportAddPassportRegistrationInfo); } else if (currentDocumentsType.type instanceof TLRPC.TL_secureValueTypeTemporaryRegistration) { noAllDocumentsErrorText = LocaleController.getString("PassportAddTemporaryRegistrationInfo", R.string.PassportAddTemporaryRegistrationInfo); } else if (currentDocumentsType.type instanceof TLRPC.TL_secureValueTypeBankStatement) { noAllDocumentsErrorText = LocaleController.getString("PassportAddBankInfo", R.string.PassportAddBankInfo); } else { noAllDocumentsErrorText = ""; } } CharSequence text = noAllDocumentsErrorText; if (documentsErrors != null) { String errorText; if ((errorText = documentsErrors.get("files_all")) != null) { SpannableStringBuilder stringBuilder = new SpannableStringBuilder(errorText); stringBuilder.append("\n\n"); stringBuilder.append(noAllDocumentsErrorText); text = stringBuilder; stringBuilder.setSpan( new ForegroundColorSpan(Theme.getColor(Theme.key_windowBackgroundWhiteRedText3)), 0, errorText.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); errorsValues.put("files_all", ""); } } bottomCell.setText(text); linearLayout2.addView(bottomCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); if (currentDocumentsType.translation_required) { headerCell = new HeaderCell(context); headerCell.setText(LocaleController.getString("PassportTranslation", R.string.PassportTranslation)); headerCell.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); linearLayout2.addView(headerCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); translationLayout = new LinearLayout(context); translationLayout.setOrientation(LinearLayout.VERTICAL); linearLayout2.addView(translationLayout, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); uploadTranslationCell = new TextSettingsCell(context); uploadTranslationCell.setBackgroundDrawable(Theme.getSelectorDrawable(true)); linearLayout2.addView(uploadTranslationCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); uploadTranslationCell.setOnClickListener(v -> { uploadingFileType = UPLOADING_TYPE_TRANSLATION; openAttachMenu(); }); bottomCellTranslation = new TextInfoPrivacyCell(context); bottomCellTranslation.setBackgroundDrawable(Theme.getThemedDrawable(context, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow)); if (currentBotId != 0) { noAllTranslationErrorText = LocaleController.getString("PassportAddTranslationUploadInfo", R.string.PassportAddTranslationUploadInfo); } else { if (currentDocumentsType.type instanceof TLRPC.TL_secureValueTypeRentalAgreement) { noAllTranslationErrorText = LocaleController.getString( "PassportAddTranslationAgreementInfo", R.string.PassportAddTranslationAgreementInfo); } else if (currentDocumentsType.type instanceof TLRPC.TL_secureValueTypeUtilityBill) { noAllTranslationErrorText = LocaleController.getString("PassportAddTranslationBillInfo", R.string.PassportAddTranslationBillInfo); } else if (currentDocumentsType.type instanceof TLRPC.TL_secureValueTypePassportRegistration) { noAllTranslationErrorText = LocaleController.getString( "PassportAddTranslationPassportRegistrationInfo", R.string.PassportAddTranslationPassportRegistrationInfo); } else if (currentDocumentsType.type instanceof TLRPC.TL_secureValueTypeTemporaryRegistration) { noAllTranslationErrorText = LocaleController.getString( "PassportAddTranslationTemporaryRegistrationInfo", R.string.PassportAddTranslationTemporaryRegistrationInfo); } else if (currentDocumentsType.type instanceof TLRPC.TL_secureValueTypeBankStatement) { noAllTranslationErrorText = LocaleController.getString("PassportAddTranslationBankInfo", R.string.PassportAddTranslationBankInfo); } else { noAllTranslationErrorText = ""; } } text = noAllTranslationErrorText; if (documentsErrors != null) { String errorText; if ((errorText = documentsErrors.get("translation_all")) != null) { SpannableStringBuilder stringBuilder = new SpannableStringBuilder(errorText); stringBuilder.append("\n\n"); stringBuilder.append(noAllTranslationErrorText); text = stringBuilder; stringBuilder.setSpan( new ForegroundColorSpan(Theme.getColor(Theme.key_windowBackgroundWhiteRedText3)), 0, errorText.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); errorsValues.put("translation_all", ""); } } bottomCellTranslation.setText(text); linearLayout2.addView(bottomCellTranslation, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); } } else { actionBar.setTitle(LocaleController.getString("PassportAddress", R.string.PassportAddress)); } headerCell = new HeaderCell(context); headerCell.setText(LocaleController.getString("PassportAddressHeader", R.string.PassportAddressHeader)); headerCell.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); linearLayout2.addView(headerCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); inputFields = new EditTextBoldCursor[FIELD_ADDRESS_COUNT]; for (int a = 0; a < FIELD_ADDRESS_COUNT; a++) { final EditTextBoldCursor field = new EditTextBoldCursor(context); inputFields[a] = field; ViewGroup container = new FrameLayout(context) { private StaticLayout errorLayout; float offsetX; @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int width = MeasureSpec.getSize(widthMeasureSpec) - AndroidUtilities.dp(34); errorLayout = field.getErrorLayout(width); if (errorLayout != null) { int lineCount = errorLayout.getLineCount(); if (lineCount > 1) { int height = AndroidUtilities.dp(64) + (errorLayout.getLineBottom(lineCount - 1) - errorLayout.getLineBottom(0)); heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY); } if (LocaleController.isRTL) { float maxW = 0; for (int a = 0; a < lineCount; a++) { float l = errorLayout.getLineLeft(a); if (l != 0) { offsetX = 0; break; } maxW = Math.max(maxW, errorLayout.getLineWidth(a)); if (a == lineCount - 1) { offsetX = width - maxW; } } } } super.onMeasure(widthMeasureSpec, heightMeasureSpec); } @Override protected void onDraw(Canvas canvas) { if (errorLayout != null) { canvas.save(); canvas.translate(AndroidUtilities.dp(21) + offsetX, field.getLineY() + AndroidUtilities.dp(3)); errorLayout.draw(canvas); canvas.restore(); } } }; container.setWillNotDraw(false); linearLayout2.addView(container, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); container.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); if (a == FIELD_ADDRESS_COUNT - 1) { extraBackgroundView = new View(context); extraBackgroundView.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); linearLayout2.addView(extraBackgroundView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 6)); } if (documentOnly && currentDocumentsType != null) { container.setVisibility(View.GONE); if (extraBackgroundView != null) { extraBackgroundView.setVisibility(View.GONE); } } inputFields[a].setTag(a); inputFields[a].setSupportRtlHint(true); inputFields[a].setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); inputFields[a].setHintColor(Theme.getColor(Theme.key_windowBackgroundWhiteHintText)); inputFields[a].setHeaderHintColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlueHeader)); inputFields[a].setTransformHintToHeader(true); inputFields[a].setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); inputFields[a].setBackgroundDrawable(null); inputFields[a].setCursorColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); inputFields[a].setCursorSize(AndroidUtilities.dp(20)); inputFields[a].setCursorWidth(1.5f); inputFields[a].setLineColors(Theme.getColor(Theme.key_windowBackgroundWhiteInputField), Theme.getColor(Theme.key_windowBackgroundWhiteInputFieldActivated), Theme.getColor(Theme.key_windowBackgroundWhiteRedText3)); if (a == FIELD_COUNTRY) { inputFields[a].setOnTouchListener((v, event) -> { if (getParentActivity() == null) { return false; } if (event.getAction() == MotionEvent.ACTION_UP) { CountrySelectActivity fragment = new CountrySelectActivity(false); fragment.setCountrySelectActivityDelegate((name, shortName) -> { inputFields[FIELD_COUNTRY].setText(name); currentCitizeship = shortName; }); presentFragment(fragment); } return true; }); inputFields[a].setInputType(0); inputFields[a].setFocusable(false); } else { inputFields[a].setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_CAP_SENTENCES); inputFields[a].setImeOptions(EditorInfo.IME_ACTION_NEXT | EditorInfo.IME_FLAG_NO_EXTRACT_UI); } String value; final String key; switch (a) { case FIELD_STREET1: inputFields[a].setHintText(LocaleController.getString("PassportStreet1", R.string.PassportStreet1)); key = "street_line1"; break; case FIELD_STREET2: inputFields[a].setHintText(LocaleController.getString("PassportStreet2", R.string.PassportStreet2)); key = "street_line2"; break; case FIELD_CITY: inputFields[a].setHintText(LocaleController.getString("PassportCity", R.string.PassportCity)); key = "city"; break; case FIELD_STATE: inputFields[a].setHintText(LocaleController.getString("PassportState", R.string.PassportState)); key = "state"; break; case FIELD_COUNTRY: inputFields[a].setHintText(LocaleController.getString("PassportCountry", R.string.PassportCountry)); key = "country_code"; break; case FIELD_POSTCODE: inputFields[a] .setHintText(LocaleController.getString("PassportPostcode", R.string.PassportPostcode)); key = "post_code"; break; default: continue; } setFieldValues(currentValues, inputFields[a], key); if (a == FIELD_POSTCODE) { inputFields[a].addTextChangedListener(new TextWatcher() { private boolean ignore; @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { } @Override public void afterTextChanged(Editable s) { if (ignore) { return; } ignore = true; boolean error = false; for (int a = 0; a < s.length(); a++) { char ch = s.charAt(a); if (!(ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch >= '0' && ch <= '9' || ch == '-' || ch == ' ')) { error = true; break; } } ignore = false; if (error) { field.setErrorText(LocaleController.getString("PassportUseLatinOnly", R.string.PassportUseLatinOnly)); } else { checkFieldForError(field, key, s, false); } } }); InputFilter[] inputFilters = new InputFilter[1]; inputFilters[0] = new InputFilter.LengthFilter(10); inputFields[a].setFilters(inputFilters); } else { inputFields[a].addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { } @Override public void afterTextChanged(Editable s) { checkFieldForError(field, key, s, false); } }); } inputFields[a].setSelection(inputFields[a].length()); inputFields[a].setPadding(0, 0, 0, 0); inputFields[a] .setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL); container.addView(inputFields[a], LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 64, Gravity.LEFT | Gravity.TOP, 21, 0, 21, 0)); inputFields[a].setOnEditorActionListener((textView, i, keyEvent) -> { if (i == EditorInfo.IME_ACTION_NEXT) { int num = (Integer) textView.getTag(); num++; if (num < inputFields.length) { if (inputFields[num].isFocusable()) { inputFields[num].requestFocus(); } else { inputFields[num] .dispatchTouchEvent(MotionEvent.obtain(0, 0, MotionEvent.ACTION_UP, 0, 0, 0)); textView.clearFocus(); AndroidUtilities.hideKeyboard(textView); } } return true; } return false; }); } sectionCell = new ShadowSectionCell(context); linearLayout2.addView(sectionCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); if (documentOnly && currentDocumentsType != null) { headerCell.setVisibility(View.GONE); sectionCell.setVisibility(View.GONE); } if ((currentBotId != 0 || currentDocumentsType == null) && currentTypeValue != null && !documentOnly || currentDocumentsTypeValue != null) { if (currentDocumentsTypeValue != null) { addDocumentViews(currentDocumentsTypeValue.files); addTranslationDocumentViews(currentDocumentsTypeValue.translation); } sectionCell.setBackgroundDrawable( Theme.getThemedDrawable(context, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow)); TextSettingsCell settingsCell1 = new TextSettingsCell(context); settingsCell1.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteRedText3)); settingsCell1.setBackgroundDrawable(Theme.getSelectorDrawable(true)); if (currentDocumentsType == null) { settingsCell1.setText(LocaleController.getString("PassportDeleteInfo", R.string.PassportDeleteInfo), false); } else { settingsCell1.setText( LocaleController.getString("PassportDeleteDocument", R.string.PassportDeleteDocument), false); } linearLayout2.addView(settingsCell1, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); settingsCell1.setOnClickListener(v -> createDocumentDeleteAlert()); sectionCell = new ShadowSectionCell(context); sectionCell.setBackgroundDrawable(Theme.getThemedDrawable(context, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow)); linearLayout2.addView(sectionCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); } else { sectionCell.setBackgroundDrawable(Theme.getThemedDrawable(context, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow)); if (documentOnly && currentDocumentsType != null) { bottomCell.setBackgroundDrawable(Theme.getThemedDrawable(context, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow)); } } updateUploadText(UPLOADING_TYPE_DOCUMENTS); updateUploadText(UPLOADING_TYPE_TRANSLATION); }
From source file:org.telegram.ui.PassportActivity.java
private void createIdentityInterface(final Context context) { languageMap = new HashMap<>(); try {/*from www . j a va 2s. c o m*/ BufferedReader reader = new BufferedReader( new InputStreamReader(context.getResources().getAssets().open("countries.txt"))); String line; while ((line = reader.readLine()) != null) { String[] args = line.split(";"); languageMap.put(args[1], args[2]); } reader.close(); } catch (Exception e) { FileLog.e(e); } topErrorCell = new TextInfoPrivacyCell(context); topErrorCell.setBackgroundDrawable( Theme.getThemedDrawable(context, R.drawable.greydivider_top, Theme.key_windowBackgroundGrayShadow)); topErrorCell.setPadding(0, AndroidUtilities.dp(7), 0, 0); linearLayout2.addView(topErrorCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); checkTopErrorCell(true); if (currentDocumentsType != null) { headerCell = new HeaderCell(context); if (documentOnly) { headerCell.setText(LocaleController.getString("PassportDocuments", R.string.PassportDocuments)); } else { headerCell.setText(LocaleController.getString("PassportRequiredDocuments", R.string.PassportRequiredDocuments)); } headerCell.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); linearLayout2.addView(headerCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); frontLayout = new LinearLayout(context); frontLayout.setOrientation(LinearLayout.VERTICAL); linearLayout2.addView(frontLayout, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); uploadFrontCell = new TextDetailSettingsCell(context); uploadFrontCell.setBackgroundDrawable(Theme.getSelectorDrawable(true)); linearLayout2.addView(uploadFrontCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); uploadFrontCell.setOnClickListener(v -> { uploadingFileType = UPLOADING_TYPE_FRONT; openAttachMenu(); }); reverseLayout = new LinearLayout(context); reverseLayout.setOrientation(LinearLayout.VERTICAL); linearLayout2.addView(reverseLayout, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); boolean divider = currentDocumentsType.selfie_required; uploadReverseCell = new TextDetailSettingsCell(context); uploadReverseCell.setBackgroundDrawable(Theme.getSelectorDrawable(true)); uploadReverseCell.setTextAndValue( LocaleController.getString("PassportReverseSide", R.string.PassportReverseSide), LocaleController.getString("PassportReverseSideInfo", R.string.PassportReverseSideInfo), divider); linearLayout2.addView(uploadReverseCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); uploadReverseCell.setOnClickListener(v -> { uploadingFileType = UPLOADING_TYPE_REVERSE; openAttachMenu(); }); if (currentDocumentsType.selfie_required) { selfieLayout = new LinearLayout(context); selfieLayout.setOrientation(LinearLayout.VERTICAL); linearLayout2.addView(selfieLayout, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); uploadSelfieCell = new TextDetailSettingsCell(context); uploadSelfieCell.setBackgroundDrawable(Theme.getSelectorDrawable(true)); uploadSelfieCell.setTextAndValue( LocaleController.getString("PassportSelfie", R.string.PassportSelfie), LocaleController.getString("PassportSelfieInfo", R.string.PassportSelfieInfo), currentType.translation_required); linearLayout2.addView(uploadSelfieCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); uploadSelfieCell.setOnClickListener(v -> { uploadingFileType = UPLOADING_TYPE_SELFIE; openAttachMenu(); }); } bottomCell = new TextInfoPrivacyCell(context); bottomCell.setBackgroundDrawable( Theme.getThemedDrawable(context, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow)); bottomCell.setText( LocaleController.getString("PassportPersonalUploadInfo", R.string.PassportPersonalUploadInfo)); linearLayout2.addView(bottomCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); if (currentDocumentsType.translation_required) { headerCell = new HeaderCell(context); headerCell.setText(LocaleController.getString("PassportTranslation", R.string.PassportTranslation)); headerCell.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); linearLayout2.addView(headerCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); translationLayout = new LinearLayout(context); translationLayout.setOrientation(LinearLayout.VERTICAL); linearLayout2.addView(translationLayout, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); uploadTranslationCell = new TextSettingsCell(context); uploadTranslationCell.setBackgroundDrawable(Theme.getSelectorDrawable(true)); linearLayout2.addView(uploadTranslationCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); uploadTranslationCell.setOnClickListener(v -> { uploadingFileType = UPLOADING_TYPE_TRANSLATION; openAttachMenu(); }); bottomCellTranslation = new TextInfoPrivacyCell(context); bottomCellTranslation.setBackgroundDrawable(Theme.getThemedDrawable(context, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow)); if (currentBotId != 0) { noAllTranslationErrorText = LocaleController.getString("PassportAddTranslationUploadInfo", R.string.PassportAddTranslationUploadInfo); } else { if (currentDocumentsType.type instanceof TLRPC.TL_secureValueTypePassport) { noAllTranslationErrorText = LocaleController.getString("PassportAddPassportInfo", R.string.PassportAddPassportInfo); } else if (currentDocumentsType.type instanceof TLRPC.TL_secureValueTypeInternalPassport) { noAllTranslationErrorText = LocaleController.getString("PassportAddInternalPassportInfo", R.string.PassportAddInternalPassportInfo); } else if (currentDocumentsType.type instanceof TLRPC.TL_secureValueTypeIdentityCard) { noAllTranslationErrorText = LocaleController.getString("PassportAddIdentityCardInfo", R.string.PassportAddIdentityCardInfo); } else if (currentDocumentsType.type instanceof TLRPC.TL_secureValueTypeDriverLicense) { noAllTranslationErrorText = LocaleController.getString("PassportAddDriverLicenceInfo", R.string.PassportAddDriverLicenceInfo); } else { noAllTranslationErrorText = ""; } } CharSequence text = noAllTranslationErrorText; if (documentsErrors != null) { String errorText; if ((errorText = documentsErrors.get("translation_all")) != null) { SpannableStringBuilder stringBuilder = new SpannableStringBuilder(errorText); stringBuilder.append("\n\n"); stringBuilder.append(noAllTranslationErrorText); text = stringBuilder; stringBuilder.setSpan( new ForegroundColorSpan(Theme.getColor(Theme.key_windowBackgroundWhiteRedText3)), 0, errorText.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); errorsValues.put("translation_all", ""); } } bottomCellTranslation.setText(text); linearLayout2.addView(bottomCellTranslation, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); } } else if (Build.VERSION.SDK_INT >= 18) { scanDocumentCell = new TextSettingsCell(context); scanDocumentCell.setBackgroundDrawable(Theme.getSelectorDrawable(true)); scanDocumentCell.setText( LocaleController.getString("PassportScanPassport", R.string.PassportScanPassport), false); linearLayout2.addView(scanDocumentCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); scanDocumentCell.setOnClickListener(v -> { if (Build.VERSION.SDK_INT >= 23 && getParentActivity() .checkSelfPermission(Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { getParentActivity().requestPermissions(new String[] { Manifest.permission.CAMERA }, 22); return; } MrzCameraActivity fragment = new MrzCameraActivity(); fragment.setDelegate(result -> { if (!TextUtils.isEmpty(result.firstName)) { inputFields[FIELD_NAME].setText(result.firstName); } if (!TextUtils.isEmpty(result.middleName)) { inputFields[FIELD_MIDNAME].setText(result.middleName); } if (!TextUtils.isEmpty(result.lastName)) { inputFields[FIELD_SURNAME].setText(result.lastName); } if (result.gender != MrzRecognizer.Result.GENDER_UNKNOWN) { switch (result.gender) { case MrzRecognizer.Result.GENDER_MALE: currentGender = "male"; inputFields[FIELD_GENDER] .setText(LocaleController.getString("PassportMale", R.string.PassportMale)); break; case MrzRecognizer.Result.GENDER_FEMALE: currentGender = "female"; inputFields[FIELD_GENDER] .setText(LocaleController.getString("PassportFemale", R.string.PassportFemale)); break; } } if (!TextUtils.isEmpty(result.nationality)) { currentCitizeship = result.nationality; String country = languageMap.get(currentCitizeship); if (country != null) { inputFields[FIELD_CITIZENSHIP].setText(country); } } if (!TextUtils.isEmpty(result.issuingCountry)) { currentResidence = result.issuingCountry; String country = languageMap.get(currentResidence); if (country != null) { inputFields[FIELD_RESIDENCE].setText(country); } } if (result.birthDay > 0 && result.birthMonth > 0 && result.birthYear > 0) { inputFields[FIELD_BIRTHDAY].setText(String.format(Locale.US, "%02d.%02d.%d", result.birthDay, result.birthMonth, result.birthYear)); } }); presentFragment(fragment); }); bottomCell = new TextInfoPrivacyCell(context); bottomCell.setBackgroundDrawable( Theme.getThemedDrawable(context, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow)); bottomCell.setText( LocaleController.getString("PassportScanPassportInfo", R.string.PassportScanPassportInfo)); linearLayout2.addView(bottomCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); } headerCell = new HeaderCell(context); if (documentOnly) { headerCell.setText(LocaleController.getString("PassportDocument", R.string.PassportDocument)); } else { headerCell.setText(LocaleController.getString("PassportPersonal", R.string.PassportPersonal)); } headerCell.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); linearLayout2.addView(headerCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); int count = currentDocumentsType != null ? FIELD_IDENTITY_COUNT : FIELD_IDENTITY_NODOC_COUNT; inputFields = new EditTextBoldCursor[count]; for (int a = 0; a < count; a++) { final EditTextBoldCursor field = new EditTextBoldCursor(context); inputFields[a] = field; ViewGroup container = new FrameLayout(context) { private StaticLayout errorLayout; private float offsetX; @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int width = MeasureSpec.getSize(widthMeasureSpec) - AndroidUtilities.dp(34); errorLayout = field.getErrorLayout(width); if (errorLayout != null) { int lineCount = errorLayout.getLineCount(); if (lineCount > 1) { int height = AndroidUtilities.dp(64) + (errorLayout.getLineBottom(lineCount - 1) - errorLayout.getLineBottom(0)); heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY); } if (LocaleController.isRTL) { float maxW = 0; for (int a = 0; a < lineCount; a++) { float l = errorLayout.getLineLeft(a); if (l != 0) { offsetX = 0; break; } maxW = Math.max(maxW, errorLayout.getLineWidth(a)); if (a == lineCount - 1) { offsetX = width - maxW; } } } } super.onMeasure(widthMeasureSpec, heightMeasureSpec); } @Override protected void onDraw(Canvas canvas) { if (errorLayout != null) { canvas.save(); canvas.translate(AndroidUtilities.dp(21) + offsetX, field.getLineY() + AndroidUtilities.dp(3)); errorLayout.draw(canvas); canvas.restore(); } } }; container.setWillNotDraw(false); linearLayout2.addView(container, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 64)); container.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); if (a == count - 1) { extraBackgroundView = new View(context); extraBackgroundView.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); linearLayout2.addView(extraBackgroundView, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 6)); } if (documentOnly && currentDocumentsType != null && a < FIELD_CARDNUMBER) { container.setVisibility(View.GONE); if (extraBackgroundView != null) { extraBackgroundView.setVisibility(View.GONE); } } inputFields[a].setTag(a); inputFields[a].setSupportRtlHint(true); inputFields[a].setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); inputFields[a].setHintColor(Theme.getColor(Theme.key_windowBackgroundWhiteHintText)); inputFields[a].setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); inputFields[a].setHeaderHintColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlueHeader)); inputFields[a].setTransformHintToHeader(true); inputFields[a].setBackgroundDrawable(null); inputFields[a].setCursorColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); inputFields[a].setCursorSize(AndroidUtilities.dp(20)); inputFields[a].setCursorWidth(1.5f); inputFields[a].setLineColors(Theme.getColor(Theme.key_windowBackgroundWhiteInputField), Theme.getColor(Theme.key_windowBackgroundWhiteInputFieldActivated), Theme.getColor(Theme.key_windowBackgroundWhiteRedText3)); if (a == FIELD_CITIZENSHIP || a == FIELD_RESIDENCE) { inputFields[a].setOnTouchListener((v, event) -> { if (getParentActivity() == null) { return false; } if (event.getAction() == MotionEvent.ACTION_UP) { CountrySelectActivity fragment = new CountrySelectActivity(false); fragment.setCountrySelectActivityDelegate((name, shortName) -> { int field12 = (Integer) v.getTag(); final EditTextBoldCursor editText = inputFields[field12]; if (field12 == FIELD_CITIZENSHIP) { currentCitizeship = shortName; } else { currentResidence = shortName; } editText.setText(name); }); presentFragment(fragment); } return true; }); inputFields[a].setInputType(0); } else if (a == FIELD_BIRTHDAY || a == FIELD_EXPIRE) { inputFields[a].setOnTouchListener((v, event) -> { if (getParentActivity() == null) { return false; } if (event.getAction() == MotionEvent.ACTION_UP) { Calendar calendar = Calendar.getInstance(); int year = calendar.get(Calendar.YEAR); int monthOfYear = calendar.get(Calendar.MONTH); int dayOfMonth = calendar.get(Calendar.DAY_OF_MONTH); try { final EditTextBoldCursor field1 = (EditTextBoldCursor) v; int num = (Integer) field1.getTag(); int minYear; int maxYear; int currentYearDiff; String title; if (num == FIELD_EXPIRE) { title = LocaleController.getString("PassportSelectExpiredDate", R.string.PassportSelectExpiredDate); minYear = 0; maxYear = 20; currentYearDiff = 0; } else { title = LocaleController.getString("PassportSelectBithdayDate", R.string.PassportSelectBithdayDate); minYear = -120; maxYear = 0; currentYearDiff = -18; } int selectedDay = -1; int selectedMonth = -1; int selectedYear = -1; String args[] = field1.getText().toString().split("\\."); if (args.length == 3) { selectedDay = Utilities.parseInt(args[0]); selectedMonth = Utilities.parseInt(args[1]); selectedYear = Utilities.parseInt(args[2]); } AlertDialog.Builder builder = AlertsCreator.createDatePickerDialog(context, minYear, maxYear, currentYearDiff, selectedDay, selectedMonth, selectedYear, title, num == FIELD_EXPIRE, (year1, month, dayOfMonth1) -> { if (num == FIELD_EXPIRE) { currentExpireDate[0] = year1; currentExpireDate[1] = month + 1; currentExpireDate[2] = dayOfMonth1; } field1.setText(String.format(Locale.US, "%02d.%02d.%d", dayOfMonth1, month + 1, year1)); }); if (num == FIELD_EXPIRE) { builder.setNegativeButton(LocaleController.getString("PassportSelectNotExpire", R.string.PassportSelectNotExpire), (dialog, which) -> { currentExpireDate[0] = currentExpireDate[1] = currentExpireDate[2] = 0; field1.setText(LocaleController.getString("PassportNoExpireDate", R.string.PassportNoExpireDate)); }); } showDialog(builder.create()); } catch (Exception e) { FileLog.e(e); } } return true; }); inputFields[a].setInputType(0); inputFields[a].setFocusable(false); } else if (a == FIELD_GENDER) { inputFields[a].setOnTouchListener((v, event) -> { if (getParentActivity() == null) { return false; } if (event.getAction() == MotionEvent.ACTION_UP) { AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); builder.setTitle( LocaleController.getString("PassportSelectGender", R.string.PassportSelectGender)); builder.setItems( new CharSequence[] { LocaleController.getString("PassportMale", R.string.PassportMale), LocaleController.getString("PassportFemale", R.string.PassportFemale) }, (dialogInterface, i) -> { if (i == 0) { currentGender = "male"; inputFields[FIELD_GENDER].setText( LocaleController.getString("PassportMale", R.string.PassportMale)); } else if (i == 1) { currentGender = "female"; inputFields[FIELD_GENDER].setText(LocaleController .getString("PassportFemale", R.string.PassportFemale)); } }); builder.setPositiveButton(LocaleController.getString("Cancel", R.string.Cancel), null); showDialog(builder.create()); } return true; }); inputFields[a].setInputType(0); inputFields[a].setFocusable(false); } else { inputFields[a].setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_CAP_SENTENCES); inputFields[a].setImeOptions(EditorInfo.IME_ACTION_NEXT | EditorInfo.IME_FLAG_NO_EXTRACT_UI); } String value; final String key; HashMap<String, String> values; switch (a) { case FIELD_NAME: if (currentType.native_names) { inputFields[a].setHintText( LocaleController.getString("PassportNameLatin", R.string.PassportNameLatin)); } else { inputFields[a].setHintText(LocaleController.getString("PassportName", R.string.PassportName)); } key = "first_name"; values = currentValues; break; case FIELD_MIDNAME: if (currentType.native_names) { inputFields[a].setHintText( LocaleController.getString("PassportMidnameLatin", R.string.PassportMidnameLatin)); } else { inputFields[a] .setHintText(LocaleController.getString("PassportMidname", R.string.PassportMidname)); } key = "middle_name"; values = currentValues; break; case FIELD_SURNAME: if (currentType.native_names) { inputFields[a].setHintText( LocaleController.getString("PassportSurnameLatin", R.string.PassportSurnameLatin)); } else { inputFields[a] .setHintText(LocaleController.getString("PassportSurname", R.string.PassportSurname)); } key = "last_name"; values = currentValues; break; case FIELD_BIRTHDAY: inputFields[a] .setHintText(LocaleController.getString("PassportBirthdate", R.string.PassportBirthdate)); key = "birth_date"; values = currentValues; break; case FIELD_GENDER: inputFields[a].setHintText(LocaleController.getString("PassportGender", R.string.PassportGender)); key = "gender"; values = currentValues; break; case FIELD_CITIZENSHIP: inputFields[a].setHintText( LocaleController.getString("PassportCitizenship", R.string.PassportCitizenship)); key = "country_code"; values = currentValues; break; case FIELD_RESIDENCE: inputFields[a] .setHintText(LocaleController.getString("PassportResidence", R.string.PassportResidence)); key = "residence_country_code"; values = currentValues; break; case FIELD_CARDNUMBER: inputFields[a].setHintText( LocaleController.getString("PassportDocumentNumber", R.string.PassportDocumentNumber)); key = "document_no"; values = currentDocumentValues; break; case FIELD_EXPIRE: inputFields[a].setHintText(LocaleController.getString("PassportExpired", R.string.PassportExpired)); key = "expiry_date"; values = currentDocumentValues; break; default: continue; } setFieldValues(values, inputFields[a], key); inputFields[a].setSelection(inputFields[a].length()); if (a == FIELD_NAME || a == FIELD_SURNAME || a == FIELD_MIDNAME) { inputFields[a].addTextChangedListener(new TextWatcher() { private boolean ignore; @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { } @Override public void afterTextChanged(Editable s) { if (ignore) { return; } int num = (Integer) field.getTag(); boolean error = false; for (int a = 0; a < s.length(); a++) { char ch = s.charAt(a); if (!(ch >= '0' && ch <= '9' || ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch == ' ' || ch == '\'' || ch == ',' || ch == '.' || ch == '&' || ch == '-' || ch == '/')) { error = true; break; } } if (error && !allowNonLatinName) { field.setErrorText(LocaleController.getString("PassportUseLatinOnly", R.string.PassportUseLatinOnly)); } else { nonLatinNames[num] = error; checkFieldForError(field, key, s, false); } } }); } else { inputFields[a].addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { } @Override public void afterTextChanged(Editable s) { checkFieldForError(field, key, s, values == currentDocumentValues); int field12 = (Integer) field.getTag(); final EditTextBoldCursor editText = inputFields[field12]; if (field12 == FIELD_RESIDENCE) { checkNativeFields(true); } } }); } inputFields[a].setPadding(0, 0, 0, 0); inputFields[a] .setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL); container.addView(inputFields[a], LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 21, 0, 21, 0)); inputFields[a].setOnEditorActionListener((textView, i, keyEvent) -> { if (i == EditorInfo.IME_ACTION_NEXT) { int num = (Integer) textView.getTag(); num++; if (num < inputFields.length) { if (inputFields[num].isFocusable()) { inputFields[num].requestFocus(); } else { inputFields[num] .dispatchTouchEvent(MotionEvent.obtain(0, 0, MotionEvent.ACTION_UP, 0, 0, 0)); textView.clearFocus(); AndroidUtilities.hideKeyboard(textView); } } return true; } return false; }); } sectionCell2 = new ShadowSectionCell(context); linearLayout2.addView(sectionCell2, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); headerCell = new HeaderCell(context); headerCell.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); linearLayout2.addView(headerCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); inputExtraFields = new EditTextBoldCursor[FIELD_NATIVE_COUNT]; for (int a = 0; a < FIELD_NATIVE_COUNT; a++) { final EditTextBoldCursor field = new EditTextBoldCursor(context); inputExtraFields[a] = field; ViewGroup container = new FrameLayout(context) { private StaticLayout errorLayout; private float offsetX; @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int width = MeasureSpec.getSize(widthMeasureSpec) - AndroidUtilities.dp(34); errorLayout = field.getErrorLayout(width); if (errorLayout != null) { int lineCount = errorLayout.getLineCount(); if (lineCount > 1) { int height = AndroidUtilities.dp(64) + (errorLayout.getLineBottom(lineCount - 1) - errorLayout.getLineBottom(0)); heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY); } if (LocaleController.isRTL) { float maxW = 0; for (int a = 0; a < lineCount; a++) { float l = errorLayout.getLineLeft(a); if (l != 0) { offsetX = 0; break; } maxW = Math.max(maxW, errorLayout.getLineWidth(a)); if (a == lineCount - 1) { offsetX = width - maxW; } } } } super.onMeasure(widthMeasureSpec, heightMeasureSpec); } @Override protected void onDraw(Canvas canvas) { if (errorLayout != null) { canvas.save(); canvas.translate(AndroidUtilities.dp(21) + offsetX, field.getLineY() + AndroidUtilities.dp(3)); errorLayout.draw(canvas); canvas.restore(); } } }; container.setWillNotDraw(false); linearLayout2.addView(container, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 64)); container.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); if (a == FIELD_NATIVE_COUNT - 1) { extraBackgroundView2 = new View(context); extraBackgroundView2.setBackgroundColor(Theme.getColor(Theme.key_windowBackgroundWhite)); linearLayout2.addView(extraBackgroundView2, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, 6)); } inputExtraFields[a].setTag(a); inputExtraFields[a].setSupportRtlHint(true); inputExtraFields[a].setTextSize(TypedValue.COMPLEX_UNIT_DIP, 16); inputExtraFields[a].setHintColor(Theme.getColor(Theme.key_windowBackgroundWhiteHintText)); inputExtraFields[a].setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); inputExtraFields[a].setHeaderHintColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlueHeader)); inputExtraFields[a].setTransformHintToHeader(true); inputExtraFields[a].setBackgroundDrawable(null); inputExtraFields[a].setCursorColor(Theme.getColor(Theme.key_windowBackgroundWhiteBlackText)); inputExtraFields[a].setCursorSize(AndroidUtilities.dp(20)); inputExtraFields[a].setCursorWidth(1.5f); inputExtraFields[a].setLineColors(Theme.getColor(Theme.key_windowBackgroundWhiteInputField), Theme.getColor(Theme.key_windowBackgroundWhiteInputFieldActivated), Theme.getColor(Theme.key_windowBackgroundWhiteRedText3)); inputExtraFields[a].setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_CAP_SENTENCES); inputExtraFields[a].setImeOptions(EditorInfo.IME_ACTION_NEXT | EditorInfo.IME_FLAG_NO_EXTRACT_UI); String value; final String key; HashMap<String, String> values; switch (a) { case FIELD_NATIVE_NAME: key = "first_name_native"; values = currentValues; break; case FIELD_NATIVE_MIDNAME: key = "middle_name_native"; values = currentValues; break; case FIELD_NATIVE_SURNAME: key = "last_name_native"; values = currentValues; break; default: continue; } setFieldValues(values, inputExtraFields[a], key); inputExtraFields[a].setSelection(inputExtraFields[a].length()); if (a == FIELD_NATIVE_NAME || a == FIELD_NATIVE_SURNAME || a == FIELD_NATIVE_MIDNAME) { inputExtraFields[a].addTextChangedListener(new TextWatcher() { private boolean ignore; @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { } @Override public void afterTextChanged(Editable s) { if (ignore) { return; } checkFieldForError(field, key, s, false); } }); } inputExtraFields[a].setPadding(0, 0, 0, 0); inputExtraFields[a] .setGravity((LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.CENTER_VERTICAL); container.addView(inputExtraFields[a], LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.MATCH_PARENT, Gravity.LEFT | Gravity.TOP, 21, 0, 21, 0)); inputExtraFields[a].setOnEditorActionListener((textView, i, keyEvent) -> { if (i == EditorInfo.IME_ACTION_NEXT) { int num = (Integer) textView.getTag(); num++; if (num < inputExtraFields.length) { if (inputExtraFields[num].isFocusable()) { inputExtraFields[num].requestFocus(); } else { inputExtraFields[num] .dispatchTouchEvent(MotionEvent.obtain(0, 0, MotionEvent.ACTION_UP, 0, 0, 0)); textView.clearFocus(); AndroidUtilities.hideKeyboard(textView); } } return true; } return false; }); } nativeInfoCell = new TextInfoPrivacyCell(context); linearLayout2.addView(nativeInfoCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); if ((currentBotId != 0 || currentDocumentsType == null) && currentTypeValue != null && !documentOnly || currentDocumentsTypeValue != null) { if (currentDocumentsTypeValue != null) { addDocumentViews(currentDocumentsTypeValue.files); if (currentDocumentsTypeValue.front_side instanceof TLRPC.TL_secureFile) { addDocumentViewInternal((TLRPC.TL_secureFile) currentDocumentsTypeValue.front_side, UPLOADING_TYPE_FRONT); } if (currentDocumentsTypeValue.reverse_side instanceof TLRPC.TL_secureFile) { addDocumentViewInternal((TLRPC.TL_secureFile) currentDocumentsTypeValue.reverse_side, UPLOADING_TYPE_REVERSE); } if (currentDocumentsTypeValue.selfie instanceof TLRPC.TL_secureFile) { addDocumentViewInternal((TLRPC.TL_secureFile) currentDocumentsTypeValue.selfie, UPLOADING_TYPE_SELFIE); } addTranslationDocumentViews(currentDocumentsTypeValue.translation); } TextSettingsCell settingsCell1 = new TextSettingsCell(context); settingsCell1.setTextColor(Theme.getColor(Theme.key_windowBackgroundWhiteRedText3)); settingsCell1.setBackgroundDrawable(Theme.getSelectorDrawable(true)); if (currentDocumentsType == null) { settingsCell1.setText(LocaleController.getString("PassportDeleteInfo", R.string.PassportDeleteInfo), false); } else { settingsCell1.setText( LocaleController.getString("PassportDeleteDocument", R.string.PassportDeleteDocument), false); } linearLayout2.addView(settingsCell1, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); settingsCell1.setOnClickListener(v -> createDocumentDeleteAlert()); nativeInfoCell.setBackgroundDrawable( Theme.getThemedDrawable(context, R.drawable.greydivider, Theme.key_windowBackgroundGrayShadow)); sectionCell = new ShadowSectionCell(context); sectionCell.setBackgroundDrawable(Theme.getThemedDrawable(context, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow)); linearLayout2.addView(sectionCell, LayoutHelper.createLinear(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); } else { nativeInfoCell.setBackgroundDrawable(Theme.getThemedDrawable(context, R.drawable.greydivider_bottom, Theme.key_windowBackgroundGrayShadow)); } updateInterfaceStringsForDocumentType(); checkNativeFields(false); }
From source file:com.sjdf.platform.xss.StringUtils.java
/** * <p>/*from ww w.j a va 2s. c om*/ * Find the Levenshtein distance between two Strings if it's less than or * equal to a given threshold. * </p> * <p/> * <p> * This is the number of changes needed to change one String into another, * where each change is a single character modification (deletion, insertion * or substitution). * </p> * <p/> * <p> * This implementation follows from Algorithms on Strings, Trees and * Sequences by Dan Gusfield and Chas Emerick's implementation of the * Levenshtein distance algorithm from <a * href="http://www.merriampark.com/ld.htm" * >http://www.merriampark.com/ld.htm</a> * </p> * <p/> * <pre> * StringUtils.getLevenshteinDistance(null, *, *) = IllegalArgumentException * StringUtils.getLevenshteinDistance(*, null, *) = IllegalArgumentException * StringUtils.getLevenshteinDistance(*, *, -1) = IllegalArgumentException * StringUtils.getLevenshteinDistance("","", 0) = 0 * StringUtils.getLevenshteinDistance("aaapppp", "", 8) = 7 * StringUtils.getLevenshteinDistance("aaapppp", "", 7) = 7 * StringUtils.getLevenshteinDistance("aaapppp", "", 6)) = -1 * StringUtils.getLevenshteinDistance("elephant", "hippo", 7) = 7 * StringUtils.getLevenshteinDistance("elephant", "hippo", 6) = -1 * StringUtils.getLevenshteinDistance("hippo", "elephant", 7) = 7 * StringUtils.getLevenshteinDistance("hippo", "elephant", 6) = -1 * </pre> * * @param ss the first String, must not be null * @param tt the second String, must not be null * @param threshold the target threshold, must not be negative * @return result distance, or {@code -1} if the distance would be greater * than the threshold * @throws IllegalArgumentException if either String input {@code null} or negative threshold */ public static int getLevenshteinDistance(CharSequence ss, CharSequence tt, int threshold) { CharSequence s = ss, t = tt; if (s == null || t == null) { throw new IllegalArgumentException("Strings must not be null"); } if (threshold < 0) { throw new IllegalArgumentException("Threshold must not be negative"); } /** * This implementation only computes the distance if it's less than or * equal to the threshold value, returning -1 if it's greater. The * advantage is performance: unbounded distance is O(nm), but a bound of * k allows us to reduce it to O(km) time by only computing a diagonal * stripe of width 2k + 1 of the cost table. It is also possible to use * this to compute the unbounded Levenshtein distance by starting the * threshold at 1 and doubling each time until the distance is found; * this is O(dm), where d is the distance. * * One subtlety comes from needing to ignore entries on the border of * our stripe eg. p[] = |#|#|#|* d[] = *|#|#|#| We must ignore the entry * to the left of the leftmost member We must ignore the entry above the * rightmost member * * Another subtlety comes from our stripe running off the matrix if the * strings aren't of the same size. Since string s is always swapped to * be the shorter of the two, the stripe will always run off to the * upper right instead of the lower left of the matrix. * * As a concrete example, suppose s is of length 5, t is of length 7, * and our threshold is 1. In this case we're going to walk a stripe of * length 3. The matrix would look like so: * * 1 2 3 4 5 1 |#|#| | | | 2 |#|#|#| | | 3 | |#|#|#| | 4 | | |#|#|#| 5 | * | | |#|#| 6 | | | | |#| 7 | | | | | | * * Note how the stripe leads off the table as there is no possible way * to turn a string of length 5 into one of length 7 in edit distance of * 1. * * Additionally, this implementation decreases memory usage by using two * single-dimensional arrays and swapping them back and forth instead of * allocating an entire n by m matrix. This requires a few minor * changes, such as immediately returning when it's detected that the * stripe has run off the matrix and initially filling the arrays with * large values so that entries we don't compute are ignored. * * See Algorithms on Strings, Trees and Sequences by Dan Gusfield for * some discussion. */ int n = s.length(); int m = t.length(); // if one string is empty, the edit distance is necessarily the length // of the other if (n == 0) { return m <= threshold ? m : -1; } else if (m == 0) { return n <= threshold ? n : -1; } if (n > m) { // swap the two strings to consume less memory CharSequence tmp = s; s = t; t = tmp; n = m; m = t.length(); } int[] p = new int[n + 1]; int[] d = new int[n + 1]; int[] pd; // fill in starting table values int boundary = Math.min(n, threshold) + 1; for (int i = 0; i < boundary; i++) { p[i] = i; } // these fills ensure that the value above the rightmost entry of our // stripe will be ignored in following loop iterations Arrays.fill(p, boundary, p.length, Integer.MAX_VALUE); Arrays.fill(d, Integer.MAX_VALUE); // iterates through t for (int j = 1; j <= m; j++) { char tj = t.charAt(j - 1); d[0] = j; // compute stripe indices, constrain to array size int min = Math.max(1, j - threshold); int max = Math.min(n, j + threshold); // the stripe may lead off of the table if s and t are of different // sizes if (min > max) { return -1; } // ignore entry left of leftmost if (min > 1) { d[min - 1] = Integer.MAX_VALUE; } // iterates through [min, max] in s for (int i = min; i <= max; i++) { if (s.charAt(i - 1) == tj) { // diagonally left and up d[i] = p[i - 1]; } else { // 1 + minimum of cell to the left, to the top, diagonally // left and up d[i] = 1 + Math.min(Math.min(d[i - 1], p[i]), p[i - 1]); } } // copy current distance counts to 'previous row' distance counts pd = p; p = d; d = pd; } // if p[n] is greater than the threshold, there's no guarantee on it // being the correct // distance if (p[n] <= threshold) { return p[n]; } else { return -1; } }
From source file:com.rdm.common.util.StringUtils.java
/** * <p>Find the Levenshtein distance between two Strings if it's less than or equal to a given * threshold.</p>//w ww . java 2 s.c om * * <p>This is the number of changes needed to change one String into * another, where each change is a single character modification (deletion, * insertion or substitution).</p> * * <p>This implementation follows from Algorithms on Strings, Trees and Sequences by Dan Gusfield * and Chas Emerick's implementation of the Levenshtein distance algorithm from * <a href="http://www.merriampark.com/ld.htm">http://www.merriampark.com/ld.htm</a></p> * * <pre> * StringUtils.getLevenshteinDistance(null, *, *) = IllegalArgumentException * StringUtils.getLevenshteinDistance(*, null, *) = IllegalArgumentException * StringUtils.getLevenshteinDistance(*, *, -1) = IllegalArgumentException * StringUtils.getLevenshteinDistance("","", 0) = 0 * StringUtils.getLevenshteinDistance("aaapppp", "", 8) = 7 * StringUtils.getLevenshteinDistance("aaapppp", "", 7) = 7 * StringUtils.getLevenshteinDistance("aaapppp", "", 6)) = -1 * StringUtils.getLevenshteinDistance("elephant", "hippo", 7) = 7 * StringUtils.getLevenshteinDistance("elephant", "hippo", 6) = -1 * StringUtils.getLevenshteinDistance("hippo", "elephant", 7) = 7 * StringUtils.getLevenshteinDistance("hippo", "elephant", 6) = -1 * </pre> * * @param s the first String, must not be null * @param t the second String, must not be null * @param threshold the target threshold, must not be negative * @return result distance, or {@code -1} if the distance would be greater than the threshold * @throws IllegalArgumentException if either String input {@code null} or negative threshold */ public static int getLevenshteinDistance(CharSequence s, CharSequence t, final int threshold) { if (s == null || t == null) { throw new IllegalArgumentException("Strings must not be null"); } if (threshold < 0) { throw new IllegalArgumentException("Threshold must not be negative"); } /* This implementation only computes the distance if it's less than or equal to the threshold value, returning -1 if it's greater. The advantage is performance: unbounded distance is O(nm), but a bound of k allows us to reduce it to O(km) time by only computing a diagonal stripe of width 2k + 1 of the cost table. It is also possible to use this to compute the unbounded Levenshtein distance by starting the threshold at 1 and doubling each time until the distance is found; this is O(dm), where d is the distance. One subtlety comes from needing to ignore entries on the border of our stripe eg. p[] = |#|#|#|* d[] = *|#|#|#| We must ignore the entry to the left of the leftmost member We must ignore the entry above the rightmost member Another subtlety comes from our stripe running off the matrix if the strings aren't of the same size. Since string s is always swapped to be the shorter of the two, the stripe will always run off to the upper right instead of the lower left of the matrix. As a concrete example, suppose s is of length 5, t is of length 7, and our threshold is 1. In this case we're going to walk a stripe of length 3. The matrix would look like so: 1 2 3 4 5 1 |#|#| | | | 2 |#|#|#| | | 3 | |#|#|#| | 4 | | |#|#|#| 5 | | | |#|#| 6 | | | | |#| 7 | | | | | | Note how the stripe leads off the table as there is no possible way to turn a string of length 5 into one of length 7 in edit distance of 1. Additionally, this implementation decreases memory usage by using two single-dimensional arrays and swapping them back and forth instead of allocating an entire n by m matrix. This requires a few minor changes, such as immediately returning when it's detected that the stripe has run off the matrix and initially filling the arrays with large values so that entries we don't compute are ignored. See Algorithms on Strings, Trees and Sequences by Dan Gusfield for some discussion. */ int n = s.length(); // length of s int m = t.length(); // length of t // if one string is empty, the edit distance is necessarily the length of the other if (n == 0) { return m <= threshold ? m : -1; } else if (m == 0) { return n <= threshold ? n : -1; } if (n > m) { // swap the two strings to consume less memory final CharSequence tmp = s; s = t; t = tmp; n = m; m = t.length(); } int p[] = new int[n + 1]; // 'previous' cost array, horizontally int d[] = new int[n + 1]; // cost array, horizontally int _d[]; // placeholder to assist in swapping p and d // fill in starting table values final int boundary = Math.min(n, threshold) + 1; for (int i = 0; i < boundary; i++) { p[i] = i; } // these fills ensure that the value above the rightmost entry of our // stripe will be ignored in following loop iterations Arrays.fill(p, boundary, p.length, Integer.MAX_VALUE); Arrays.fill(d, Integer.MAX_VALUE); // iterates through t for (int j = 1; j <= m; j++) { final char t_j = t.charAt(j - 1); // jth character of t d[0] = j; // compute stripe indices, constrain to array size final int min = Math.max(1, j - threshold); final int max = (j > Integer.MAX_VALUE - threshold) ? n : Math.min(n, j + threshold); // the stripe may lead off of the table if s and t are of different sizes if (min > max) { return -1; } // ignore entry left of leftmost if (min > 1) { d[min - 1] = Integer.MAX_VALUE; } // iterates through [min, max] in s for (int i = min; i <= max; i++) { if (s.charAt(i - 1) == t_j) { // diagonally left and up d[i] = p[i - 1]; } else { // 1 + minimum of cell to the left, to the top, diagonally left and up d[i] = 1 + Math.min(Math.min(d[i - 1], p[i]), p[i - 1]); } } // copy current distance counts to 'previous row' distance counts _d = p; p = d; d = _d; } // if p[n] is greater than the threshold, there's no guarantee on it being the correct // distance if (p[n] <= threshold) { return p[n]; } return -1; }
From source file:net.bluehack.ui.ChatActivity.java
private void searchLinks(final CharSequence charSequence, final boolean force) { if (currentEncryptedChat != null && (MessagesController.getInstance().secretWebpagePreview == 0 || AndroidUtilities.getPeerLayerVersion(currentEncryptedChat.layer) < 46)) { return;/* w ww.j a v a 2 s. com*/ } if (force && foundWebPage != null) { if (foundWebPage.url != null) { int index = TextUtils.indexOf(charSequence, foundWebPage.url); char lastChar = 0; boolean lenEqual = false; if (index == -1) { if (foundWebPage.display_url != null) { index = TextUtils.indexOf(charSequence, foundWebPage.display_url); lenEqual = index != -1 && index + foundWebPage.display_url.length() == charSequence.length(); lastChar = index != -1 && !lenEqual ? charSequence.charAt(index + foundWebPage.display_url.length()) : 0; } } else { lenEqual = index + foundWebPage.url.length() == charSequence.length(); lastChar = !lenEqual ? charSequence.charAt(index + foundWebPage.url.length()) : 0; } if (index != -1 && (lenEqual || lastChar == ' ' || lastChar == ',' || lastChar == '.' || lastChar == '!' || lastChar == '/')) { return; } } pendingLinkSearchString = null; showReplyPanel(false, null, null, foundWebPage, false, true); } Utilities.searchQueue.postRunnable(new Runnable() { @Override public void run() { if (linkSearchRequestId != 0) { ConnectionsManager.getInstance().cancelRequest(linkSearchRequestId, true); linkSearchRequestId = 0; } ArrayList<CharSequence> urls = null; CharSequence textToCheck; try { Matcher m = AndroidUtilities.WEB_URL.matcher(charSequence); while (m.find()) { if (m.start() > 0) { if (charSequence.charAt(m.start() - 1) == '@') { continue; } } if (urls == null) { urls = new ArrayList<>(); } urls.add(charSequence.subSequence(m.start(), m.end())); } if (urls != null && foundUrls != null && urls.size() == foundUrls.size()) { boolean clear = true; for (int a = 0; a < urls.size(); a++) { if (!TextUtils.equals(urls.get(a), foundUrls.get(a))) { clear = false; } } if (clear) { return; } } foundUrls = urls; if (urls == null) { AndroidUtilities.runOnUIThread(new Runnable() { @Override public void run() { if (foundWebPage != null) { showReplyPanel(false, null, null, foundWebPage, false, true); foundWebPage = null; } } }); return; } textToCheck = TextUtils.join(" ", urls); } catch (Exception e) { FileLog.e("tmessages", e); String text = charSequence.toString().toLowerCase(); if (charSequence.length() < 13 || !text.contains("http://") && !text.contains("https://")) { AndroidUtilities.runOnUIThread(new Runnable() { @Override public void run() { if (foundWebPage != null) { showReplyPanel(false, null, null, foundWebPage, false, true); foundWebPage = null; } } }); return; } textToCheck = charSequence; } if (currentEncryptedChat != null && MessagesController.getInstance().secretWebpagePreview == 2) { AndroidUtilities.runOnUIThread(new Runnable() { @Override public void run() { AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); builder.setTitle(LocaleController.getString("AppName", R.string.AppName)); builder.setPositiveButton(LocaleController.getString("OK", R.string.OK), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { MessagesController.getInstance().secretWebpagePreview = 1; ApplicationLoader.applicationContext .getSharedPreferences("mainconfig", Activity.MODE_PRIVATE) .edit() .putInt("secretWebpage2", MessagesController.getInstance().secretWebpagePreview) .commit(); foundUrls = null; searchLinks(charSequence, force); } }); builder.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), null); builder.setMessage(LocaleController.getString("SecretLinkPreviewAlert", R.string.SecretLinkPreviewAlert)); showDialog(builder.create()); MessagesController.getInstance().secretWebpagePreview = 0; ApplicationLoader.applicationContext .getSharedPreferences("mainconfig", Activity.MODE_PRIVATE).edit() .putInt("secretWebpage2", MessagesController.getInstance().secretWebpagePreview) .commit(); } }); return; } final TLRPC.TL_messages_getWebPagePreview req = new TLRPC.TL_messages_getWebPagePreview(); if (textToCheck instanceof String) { req.message = (String) textToCheck; } else { req.message = textToCheck.toString(); } linkSearchRequestId = ConnectionsManager.getInstance().sendRequest(req, new RequestDelegate() { @Override public void run(final TLObject response, final TLRPC.TL_error error) { AndroidUtilities.runOnUIThread(new Runnable() { @Override public void run() { linkSearchRequestId = 0; if (error == null) { if (response instanceof TLRPC.TL_messageMediaWebPage) { foundWebPage = ((TLRPC.TL_messageMediaWebPage) response).webpage; if (foundWebPage instanceof TLRPC.TL_webPage || foundWebPage instanceof TLRPC.TL_webPagePending) { if (foundWebPage instanceof TLRPC.TL_webPagePending) { pendingLinkSearchString = req.message; } if (currentEncryptedChat != null && foundWebPage instanceof TLRPC.TL_webPagePending) { foundWebPage.url = req.message; } showReplyPanel(true, null, null, foundWebPage, false, true); } else { if (foundWebPage != null) { showReplyPanel(false, null, null, foundWebPage, false, true); foundWebPage = null; } } } else { if (foundWebPage != null) { showReplyPanel(false, null, null, foundWebPage, false, true); foundWebPage = null; } } } } }); } }); ConnectionsManager.getInstance().bindRequestToGuid(linkSearchRequestId, classGuid); } }); }
From source file:kr.wdream.ui.ChatActivity.java
private void searchLinks(final CharSequence charSequence, final boolean force) { if (currentEncryptedChat != null && (MessagesController.getInstance().secretWebpagePreview == 0 || AndroidUtilities.getPeerLayerVersion(currentEncryptedChat.layer) < 46)) { return;/*ww w . ja va 2 s . com*/ } if (force && foundWebPage != null) { if (foundWebPage.url != null) { int index = TextUtils.indexOf(charSequence, foundWebPage.url); char lastChar = 0; boolean lenEqual = false; if (index == -1) { if (foundWebPage.display_url != null) { index = TextUtils.indexOf(charSequence, foundWebPage.display_url); lenEqual = index != -1 && index + foundWebPage.display_url.length() == charSequence.length(); lastChar = index != -1 && !lenEqual ? charSequence.charAt(index + foundWebPage.display_url.length()) : 0; } } else { lenEqual = index + foundWebPage.url.length() == charSequence.length(); lastChar = !lenEqual ? charSequence.charAt(index + foundWebPage.url.length()) : 0; } if (index != -1 && (lenEqual || lastChar == ' ' || lastChar == ',' || lastChar == '.' || lastChar == '!' || lastChar == '/')) { return; } } pendingLinkSearchString = null; showReplyPanel(false, null, null, foundWebPage, false, true); } Utilities.searchQueue.postRunnable(new Runnable() { @Override public void run() { if (linkSearchRequestId != 0) { ConnectionsManager.getInstance().cancelRequest(linkSearchRequestId, true); linkSearchRequestId = 0; } ArrayList<CharSequence> urls = null; CharSequence textToCheck; try { Matcher m = AndroidUtilities.WEB_URL.matcher(charSequence); while (m.find()) { if (m.start() > 0) { if (charSequence.charAt(m.start() - 1) == '@') { continue; } } if (urls == null) { urls = new ArrayList<>(); } urls.add(charSequence.subSequence(m.start(), m.end())); } if (urls != null && foundUrls != null && urls.size() == foundUrls.size()) { boolean clear = true; for (int a = 0; a < urls.size(); a++) { if (!TextUtils.equals(urls.get(a), foundUrls.get(a))) { clear = false; } } if (clear) { return; } } foundUrls = urls; if (urls == null) { AndroidUtilities.runOnUIThread(new Runnable() { @Override public void run() { if (foundWebPage != null) { showReplyPanel(false, null, null, foundWebPage, false, true); foundWebPage = null; } } }); return; } textToCheck = TextUtils.join(" ", urls); } catch (Exception e) { FileLog.e("tmessages", e); String text = charSequence.toString().toLowerCase(); if (charSequence.length() < 13 || !text.contains("http://") && !text.contains("https://")) { AndroidUtilities.runOnUIThread(new Runnable() { @Override public void run() { if (foundWebPage != null) { showReplyPanel(false, null, null, foundWebPage, false, true); foundWebPage = null; } } }); return; } textToCheck = charSequence; } if (currentEncryptedChat != null && MessagesController.getInstance().secretWebpagePreview == 2) { AndroidUtilities.runOnUIThread(new Runnable() { @Override public void run() { AlertDialog.Builder builder = new AlertDialog.Builder(getParentActivity()); builder.setTitle( LocaleController.getString("AppName", kr.wdream.storyshop.R.string.AppName)); builder.setPositiveButton( LocaleController.getString("OK", kr.wdream.storyshop.R.string.OK), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { MessagesController.getInstance().secretWebpagePreview = 1; ApplicationLoader.applicationContext .getSharedPreferences("mainconfig", Activity.MODE_PRIVATE) .edit() .putInt("secretWebpage2", MessagesController.getInstance().secretWebpagePreview) .commit(); foundUrls = null; searchLinks(charSequence, force); } }); builder.setNegativeButton( LocaleController.getString("Cancel", kr.wdream.storyshop.R.string.Cancel), null); builder.setMessage(LocaleController.getString("SecretLinkPreviewAlert", kr.wdream.storyshop.R.string.SecretLinkPreviewAlert)); showDialog(builder.create()); MessagesController.getInstance().secretWebpagePreview = 0; ApplicationLoader.applicationContext .getSharedPreferences("mainconfig", Activity.MODE_PRIVATE).edit() .putInt("secretWebpage2", MessagesController.getInstance().secretWebpagePreview) .commit(); } }); return; } final TLRPC.TL_messages_getWebPagePreview req = new TLRPC.TL_messages_getWebPagePreview(); if (textToCheck instanceof String) { req.message = (String) textToCheck; } else { req.message = textToCheck.toString(); } linkSearchRequestId = ConnectionsManager.getInstance().sendRequest(req, new RequestDelegate() { @Override public void run(final TLObject response, final TLRPC.TL_error error) { AndroidUtilities.runOnUIThread(new Runnable() { @Override public void run() { linkSearchRequestId = 0; if (error == null) { if (response instanceof TLRPC.TL_messageMediaWebPage) { foundWebPage = ((TLRPC.TL_messageMediaWebPage) response).webpage; if (foundWebPage instanceof TLRPC.TL_webPage || foundWebPage instanceof TLRPC.TL_webPagePending) { if (foundWebPage instanceof TLRPC.TL_webPagePending) { pendingLinkSearchString = req.message; } if (currentEncryptedChat != null && foundWebPage instanceof TLRPC.TL_webPagePending) { foundWebPage.url = req.message; } showReplyPanel(true, null, null, foundWebPage, false, true); } else { if (foundWebPage != null) { showReplyPanel(false, null, null, foundWebPage, false, true); foundWebPage = null; } } } else { if (foundWebPage != null) { showReplyPanel(false, null, null, foundWebPage, false, true); foundWebPage = null; } } } } }); } }); ConnectionsManager.getInstance().bindRequestToGuid(linkSearchRequestId, classGuid); } }); }
From source file:bfile.util.StringUtils.java
/** * <p>Find the Levenshtein distance between two Strings if it's less than or equal to a given * threshold.</p>/*w w w . j a va 2 s .com*/ * * <p>This is the number of changes needed to change one String into * another, where each change is a single character modification (deletion, * insertion or substitution).</p> * * <p>This implementation follows from Algorithms on Strings, Trees and Sequences by Dan Gusfield * and Chas Emerick's implementation of the Levenshtein distance algorithm from * <a href="http://www.merriampark.com/ld.htm">http://www.merriampark.com/ld.htm</a></p> * * <pre> * StringUtils.getLevenshteinDistance(null, *, *) = IllegalArgumentException * StringUtils.getLevenshteinDistance(*, null, *) = IllegalArgumentException * StringUtils.getLevenshteinDistance(*, *, -1) = IllegalArgumentException * StringUtils.getLevenshteinDistance("","", 0) = 0 * StringUtils.getLevenshteinDistance("aaapppp", "", 8) = 7 * StringUtils.getLevenshteinDistance("aaapppp", "", 7) = 7 * StringUtils.getLevenshteinDistance("aaapppp", "", 6)) = -1 * StringUtils.getLevenshteinDistance("elephant", "hippo", 7) = 7 * StringUtils.getLevenshteinDistance("elephant", "hippo", 6) = -1 * StringUtils.getLevenshteinDistance("hippo", "elephant", 7) = 7 * StringUtils.getLevenshteinDistance("hippo", "elephant", 6) = -1 * </pre> * * @param s the first String, must not be null * @param t the second String, must not be null * @param threshold the target threshold, must not be negative * @return result distance, or {@code -1} if the distance would be greater than the threshold * @throws IllegalArgumentException if either String input {@code null} or negative threshold */ public static int getLevenshteinDistance(CharSequence s, CharSequence t, final int threshold) { if (s == null || t == null) { throw new IllegalArgumentException("Strings must not be null"); } if (threshold < 0) { throw new IllegalArgumentException("Threshold must not be negative"); } /* This implementation only computes the distance if it's less than or equal to the threshold value, returning -1 if it's greater. The advantage is performance: unbounded distance is O(nm), but a bound of k allows us to reduce it to O(km) time by only computing a diagonal stripe of width 2k + 1 of the cost table. It is also possible to use this to compute the unbounded Levenshtein distance by starting the threshold at 1 and doubling each time until the distance is found; this is O(dm), where d is the distance. One subtlety comes from needing to ignore entries on the border of our stripe eg. p[] = |#|#|#|* d[] = *|#|#|#| We must ignore the entry to the left of the leftmost member We must ignore the entry above the rightmost member Another subtlety comes from our stripe running off the matrix if the strings aren't of the same size. Since string s is always swapped to be the shorter of the two, the stripe will always run off to the upper right instead of the lower left of the matrix. As a concrete example, suppose s is of length 5, t is of length 7, and our threshold is 1. In this case we're going to walk a stripe of length 3. The matrix would look like so: 1 2 3 4 5 1 |#|#| | | | 2 |#|#|#| | | 3 | |#|#|#| | 4 | | |#|#|#| 5 | | | |#|#| 6 | | | | |#| 7 | | | | | | Note how the stripe leads off the table as there is no possible way to turn a string of length 5 into one of length 7 in edit distance of 1. Additionally, this implementation decreases memory usage by using two single-dimensional arrays and swapping them back and forth instead of allocating an entire n by m matrix. This requires a few minor changes, such as immediately returning when it's detected that the stripe has run off the matrix and initially filling the arrays with large values so that entries we don't compute are ignored. See Algorithms on Strings, Trees and Sequences by Dan Gusfield for some discussion. */ int n = s.length(); // length of s int m = t.length(); // length of t // if one string is empty, the edit distance is necessarily the length of the other if (n == 0) { return m <= threshold ? m : -1; } else if (m == 0) { return n <= threshold ? n : -1; } // no need to calculate the distance if the length difference is greater than the threshold else if (Math.abs(n - m) > threshold) { return -1; } if (n > m) { // swap the two strings to consume less memory final CharSequence tmp = s; s = t; t = tmp; n = m; m = t.length(); } int p[] = new int[n + 1]; // 'previous' cost array, horizontally int d[] = new int[n + 1]; // cost array, horizontally int _d[]; // placeholder to assist in swapping p and d // fill in starting table values final int boundary = Math.min(n, threshold) + 1; for (int i = 0; i < boundary; i++) { p[i] = i; } // these fills ensure that the value above the rightmost entry of our // stripe will be ignored in following loop iterations Arrays.fill(p, boundary, p.length, Integer.MAX_VALUE); Arrays.fill(d, Integer.MAX_VALUE); // iterates through t for (int j = 1; j <= m; j++) { final char t_j = t.charAt(j - 1); // jth character of t d[0] = j; // compute stripe indices, constrain to array size final int min = Math.max(1, j - threshold); final int max = j > Integer.MAX_VALUE - threshold ? n : Math.min(n, j + threshold); // the stripe may lead off of the table if s and t are of different sizes if (min > max) { return -1; } // ignore entry left of leftmost if (min > 1) { d[min - 1] = Integer.MAX_VALUE; } // iterates through [min, max] in s for (int i = min; i <= max; i++) { if (s.charAt(i - 1) == t_j) { // diagonally left and up d[i] = p[i - 1]; } else { // 1 + minimum of cell to the left, to the top, diagonally left and up d[i] = 1 + Math.min(Math.min(d[i - 1], p[i]), p[i - 1]); } } // copy current distance counts to 'previous row' distance counts _d = p; p = d; d = _d; } // if p[n] is greater than the threshold, there's no guarantee on it being the correct // distance if (p[n] <= threshold) { return p[n]; } return -1; }
From source file:com.clark.func.Functions.java
/** * <p>// ww w .ja v a 2 s . com * Checks if the CharSequence contains only ASCII printable characters. * </p> * * <p> * <code>null</code> will return <code>false</code>. An empty CharSequence * (length()=0) will return <code>true</code>. * </p> * * <pre> * isAsciiPrintable(null) = false * isAsciiPrintable("") = true * isAsciiPrintable(" ") = true * isAsciiPrintable("Ceki") = true * isAsciiPrintable("ab2c") = true * isAsciiPrintable("!ab-c~") = true * isAsciiPrintable("\u0020") = true * isAsciiPrintable("\u0021") = true * isAsciiPrintable("\u007e") = true * isAsciiPrintable("\u007f") = false * isAsciiPrintable("Ceki G\u00fclc\u00fc") = false * </pre> * * @param cs * the CharSequence to check, may be null * @return <code>true</code> if every character is in the range 32 thru 126 * @since 2.1 * @since 3.0 Changed signature from isAsciiPrintable(String) to * isAsciiPrintable(CharSequence) */ public static boolean isAsciiPrintable(CharSequence cs) { if (cs == null) { return false; } int sz = cs.length(); for (int i = 0; i < sz; i++) { if (isAsciiPrintable(cs.charAt(i)) == false) { return false; } } return true; }
From source file:com.clark.func.Functions.java
/** * <p>/*from w w w. ja va 2 s.c o m*/ * Checks if the CharSequence contains only unicode digits. A decimal point * is not a unicode digit and returns false. * </p> * * <p> * <code>null</code> will return <code>false</code>. An empty CharSequence * (length()=0) will return <code>true</code>. * </p> * * <pre> * isNumeric(null) = false * isNumeric("") = true * isNumeric(" ") = false * isNumeric("123") = true * isNumeric("12 3") = false * isNumeric("ab2c") = false * isNumeric("12-3") = false * isNumeric("12.3") = false * </pre> * * @param cs * the CharSequence to check, may be null * @return <code>true</code> if only contains digits, and is non-null * @since 3.0 Changed signature from isNumeric(String) to * isNumeric(CharSequence) */ public static boolean isNumeric(CharSequence cs) { if (cs == null) { return false; } int sz = cs.length(); for (int i = 0; i < sz; i++) { if (Character.isDigit(cs.charAt(i)) == false) { return false; } } return true; }