Home | History | Annotate | Download | only in utils
      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