1 /** 2 * Copyright (c) 2011, Google Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.mail.utils; 18 19 import android.content.res.Resources; 20 import android.text.TextUtils; 21 22 import com.android.mail.R; 23 import com.android.mail.providers.Account; 24 import com.android.mail.providers.AccountObserver; 25 import com.android.mail.ui.AccountController; 26 27 import java.util.regex.Pattern; 28 29 /** 30 * A veiled email address is where we don't want to display the email address, because the address 31 * might be throw-away, or temporary. For these veiled addresses, we want to display some alternate 32 * information. To find if an email address is veiled, call the method 33 * {@link #isVeiledAddress(String)} 34 */ 35 public final class VeiledAddressMatcher{ 36 /** 37 * Resource for the regex pattern that specifies a veiled addresses. 38 */ 39 private static final int VEILED_RESOURCE = R.string.veiled_address; 40 41 /** 42 * Resource that specifies whether veiled address matching is enabled. 43 */ 44 private static final int VEILED_MATCHING_ENABLED = R.bool.veiled_address_enabled; 45 46 /** 47 * Similar to {@link #VEILED_ALTERNATE_TEXT} except this is for addresses where we don't have 48 * the name corresponding to the veiled address. Since we don't show the address, we should 49 * indicate that the recipient is unknown to us. 50 */ 51 public static final int VEILED_ALTERNATE_TEXT_UNKNOWN_PERSON = 52 R.string.veiled_alternate_text_unknown_person; 53 54 /** 55 * When we show a veiled address, we should show an alternate string rather than the email 56 * address. This is the resource that specifies the alternate string. 57 */ 58 public static final int VEILED_ALTERNATE_TEXT = R.string.veiled_alternate_text; 59 60 /** 61 * A summary string (short-string) for an unknown veiled recipient. 62 */ 63 public static final int VEILED_SUMMARY_UNKNOWN = R.string.veiled_summary_unknown_person; 64 65 /** 66 * Private object that does the actual matching. 67 */ 68 private Pattern mMatcher = null; 69 70 /** 71 * True if veiled address matching is enabled, false otherwise. 72 */ 73 protected boolean mVeiledMatchingEnabled = false; 74 75 /** 76 * The hash code of the last profile pattern retrieved . This allows us to avoid recompiling the 77 * patterns when nothing has changed. 78 */ 79 private int mProfilePatternLastHash = -1; 80 81 private final AccountObserver mObserver = new AccountObserver() { 82 @Override 83 public void onChanged(Account newAccount) { 84 loadPattern(newAccount.settings.veiledAddressPattern); 85 } 86 }; 87 88 /** 89 * Make instantiation impossible. 90 */ 91 private VeiledAddressMatcher() { 92 // Do nothing. 93 } 94 95 /** 96 * Loads the regular expression that corresponds to veiled addresses. It is safe to call this 97 * method repeatedly with the same pattern. If the pattern has not changed, little extra work 98 * is done. 99 * @param pattern 100 */ 101 private final void loadPattern(String pattern) { 102 if (!TextUtils.isEmpty(pattern)) { 103 final int hashCode = pattern.hashCode(); 104 if (hashCode != mProfilePatternLastHash) { 105 mProfilePatternLastHash = hashCode; 106 mMatcher = Pattern.compile(pattern); 107 // Since we have a non-empty pattern now, enable pattern matching. 108 mVeiledMatchingEnabled = true; 109 } 110 } 111 } 112 113 /** 114 * Default constructor 115 * @return 116 */ 117 public static final VeiledAddressMatcher newInstance(Resources resources) { 118 final VeiledAddressMatcher instance = new VeiledAddressMatcher(); 119 instance.mVeiledMatchingEnabled = resources.getBoolean(VEILED_MATCHING_ENABLED); 120 if (instance.mVeiledMatchingEnabled) { 121 instance.loadPattern(resources.getString(VEILED_RESOURCE)); 122 } 123 return instance; 124 } 125 126 /** 127 * Initialize the object to listen for account changes. Without this, we cannot obtain updated 128 * values of the veiled address pattern and the value is read once from resources. 129 * @param controller 130 */ 131 public final void initialize(AccountController controller) { 132 mObserver.initialize(controller); 133 } 134 135 /** 136 * Returns true if the given email address is a throw-away (or veiled) address. Such addresses 137 * are created using special server-side logic for the purpose of keeping the real address of 138 * the user hidden. 139 * @param address 140 * @return true if the address is veiled, false otherwise. 141 */ 142 public final boolean isVeiledAddress (String address) { 143 if (!mVeiledMatchingEnabled || mMatcher == null) { 144 // Veiled address matching is explicitly disabled: Match nothing. 145 return false; 146 } 147 return mMatcher.matcher(address).matches(); 148 } 149 } 150