Home | History | Annotate | Download | only in model
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      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 package com.example.android.autofillframework.service.model;
     17 
     18 import android.service.autofill.Dataset;
     19 import android.support.annotation.NonNull;
     20 import android.util.Log;
     21 import android.view.View;
     22 import android.view.autofill.AutofillId;
     23 import android.view.autofill.AutofillValue;
     24 
     25 import org.json.JSONException;
     26 import org.json.JSONObject;
     27 
     28 import java.util.HashMap;
     29 import java.util.Iterator;
     30 import java.util.List;
     31 import java.util.Set;
     32 
     33 /**
     34  * ClientFormData is the model that holds all of the data on a client app's page, plus the dataset
     35  * name associated with it.
     36  */
     37 public final class ClientFormData {
     38     private static final String TAG = "ClientFormData";
     39     private final HashMap<String, SavedAutofillValue> hintMap;
     40     private String datasetName;
     41 
     42     public ClientFormData() {
     43         this(null, new HashMap<String, SavedAutofillValue>());
     44     }
     45 
     46     public ClientFormData(String datasetName, HashMap<String, SavedAutofillValue> hintMap) {
     47         this.hintMap = hintMap;
     48         this.datasetName = datasetName;
     49     }
     50 
     51     public static ClientFormData fromJson(JSONObject jsonObject) {
     52         HashMap<String, SavedAutofillValue> hintMap = new HashMap<>();
     53         try {
     54             String datasetName = jsonObject.has("datasetName") ?
     55                     jsonObject.getString("datasetName") : null;
     56             JSONObject valuesJson = jsonObject.getJSONObject("values");
     57             Iterator<String> hints = valuesJson.keys();
     58             while (hints.hasNext()) {
     59                 String hint = hints.next();
     60                 JSONObject valueAsJson = valuesJson
     61                         .getJSONObject(hint);
     62                 if (valueAsJson != null) {
     63                     SavedAutofillValue savedAutofillValue = SavedAutofillValue.fromJson(valueAsJson);
     64                     hintMap.put(hint, savedAutofillValue);
     65                 }
     66             }
     67             return new ClientFormData(datasetName, hintMap);
     68         } catch (JSONException e) {
     69             Log.d(TAG, e.getMessage());
     70             return null;
     71         }
     72     }
     73 
     74     /**
     75      * Returns the name of the {@link Dataset}.
     76      */
     77     public String getDatasetName() {
     78         return this.datasetName;
     79     }
     80 
     81     /**
     82      * Sets the {@link Dataset} name.
     83      */
     84     public void setDatasetName(String datasetName) {
     85         this.datasetName = datasetName;
     86     }
     87 
     88     /**
     89      * Sets values for a list of hints.
     90      */
     91     public void set(@NonNull String[] autofillHints, @NonNull SavedAutofillValue autofillValue) {
     92         if (autofillHints.length < 1) {
     93             return;
     94         }
     95         for (int i = 0; i < autofillHints.length; i++) {
     96             hintMap.put(autofillHints[i], autofillValue);
     97         }
     98     }
     99 
    100     /**
    101      * Populates a {@link Dataset.Builder} with appropriate values for each {@link AutofillId}
    102      * in a {@code AutofillFieldsCollection}.
    103      */
    104     public boolean applyToFields(AutofillFieldsCollection autofillFieldsCollection,
    105             Dataset.Builder datasetBuilder) {
    106         boolean setValueAtLeastOnce = false;
    107         List<String> allHints = autofillFieldsCollection.getAllHints();
    108         for (int hintIndex = 0; hintIndex < allHints.size(); hintIndex++) {
    109             String hint = allHints.get(hintIndex);
    110             List<AutofillField> autofillFields = autofillFieldsCollection.getFieldsForHint(hint);
    111             if (autofillFields == null) {
    112                 continue;
    113             }
    114             for (int autofillFieldIndex = 0; autofillFieldIndex < autofillFields.size(); autofillFieldIndex++) {
    115                 AutofillField autofillField = autofillFields.get(autofillFieldIndex);
    116                 AutofillId autofillId = autofillField.getId();
    117                 int autofillType = autofillField.getAutofillType();
    118                 SavedAutofillValue savedAutofillValue = hintMap.get(hint);
    119                 switch (autofillType) {
    120                     case View.AUTOFILL_TYPE_LIST:
    121                         int listValue = autofillField.getAutofillOptionIndex(savedAutofillValue.getTextValue());
    122                         if (listValue != -1) {
    123                             datasetBuilder.setValue(autofillId, AutofillValue.forList(listValue));
    124                             setValueAtLeastOnce = true;
    125                         }
    126                         break;
    127                     case View.AUTOFILL_TYPE_DATE:
    128                         long dateValue = savedAutofillValue.getDateValue();
    129                         if (dateValue != -1) {
    130                             datasetBuilder.setValue(autofillId, AutofillValue.forDate(dateValue));
    131                             setValueAtLeastOnce = true;
    132                         }
    133                         break;
    134                     case View.AUTOFILL_TYPE_TEXT:
    135                         String textValue = savedAutofillValue.getTextValue();
    136                         if (textValue != null) {
    137                             datasetBuilder.setValue(autofillId, AutofillValue.forText(textValue));
    138                             setValueAtLeastOnce = true;
    139                         }
    140                         break;
    141                     case View.AUTOFILL_TYPE_TOGGLE:
    142                         if (savedAutofillValue.hasToggleValue()) {
    143                             boolean toggleValue = savedAutofillValue.getToggleValue();
    144                             datasetBuilder.setValue(autofillId, AutofillValue.forToggle(toggleValue));
    145                             setValueAtLeastOnce = true;
    146                         }
    147                         break;
    148                     case View.AUTOFILL_TYPE_NONE:
    149                     default:
    150                         Log.w(TAG, "Invalid autofill type - " + autofillType);
    151                         break;
    152                 }
    153             }
    154         }
    155         return setValueAtLeastOnce;
    156     }
    157 
    158     public JSONObject toJson() {
    159         JSONObject jsonObject = new JSONObject();
    160         try {
    161             jsonObject.put("datasetName", datasetName != null ? datasetName : JSONObject.NULL);
    162             JSONObject jsonValues = new JSONObject();
    163             Set<String> hints = hintMap.keySet();
    164             for (String hint : hints) {
    165                 SavedAutofillValue value = hintMap.get(hint);
    166                 jsonValues.put(hint, value != null ? value.toJson() : JSONObject.NULL);
    167             }
    168             jsonObject.put("values", jsonValues);
    169         } catch (JSONException e) {
    170             Log.e(TAG, e.getMessage());
    171         }
    172         return jsonObject;
    173     }
    174 
    175     public boolean helpsWithHints(List<String> autofillHints) {
    176         for (int i = 0; i < autofillHints.size(); i++) {
    177             String autofillHint = autofillHints.get(i);
    178             if (hintMap.get(autofillHint) != null && !hintMap.get(autofillHint).isNull()) {
    179                 return true;
    180             }
    181         }
    182         return false;
    183     }
    184 }
    185