Home | History | Annotate | Download | only in src
      1 // Copyright (C) 2013 Google Inc.
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 // http://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 
     15 #include "retriever.h"
     16 
     17 #include <libaddressinput/callback.h>
     18 #include <libaddressinput/source.h>
     19 #include <libaddressinput/storage.h>
     20 #include <libaddressinput/util/basictypes.h>
     21 #include <libaddressinput/util/scoped_ptr.h>
     22 
     23 #include <cassert>
     24 #include <cstddef>
     25 #include <string>
     26 
     27 #include "validating_storage.h"
     28 
     29 namespace i18n {
     30 namespace addressinput {
     31 
     32 namespace {
     33 
     34 class Helper {
     35  public:
     36   // Does not take ownership of its parameters.
     37   Helper(const std::string& key,
     38          const Retriever::Callback& retrieved,
     39          const Source& source,
     40          ValidatingStorage* storage)
     41       : retrieved_(retrieved),
     42         source_(source),
     43         storage_(storage),
     44         fresh_data_ready_(BuildCallback(this, &Helper::OnFreshDataReady)),
     45         validated_data_ready_(
     46             BuildCallback(this, &Helper::OnValidatedDataReady)),
     47         stale_data_() {
     48     assert(storage_ != NULL);
     49     storage_->Get(key, *validated_data_ready_);
     50   }
     51 
     52  private:
     53   ~Helper() {}
     54 
     55   void OnValidatedDataReady(bool success,
     56                             const std::string& key,
     57                             std::string* data) {
     58     if (success) {
     59       assert(data != NULL);
     60       retrieved_(success, key, *data);
     61       delete this;
     62     } else {
     63       // Validating storage returns (false, key, stale-data) for valid but stale
     64       // data. If |data| is empty, however, then it's either missing or invalid.
     65       if (data != NULL && !data->empty()) {
     66         stale_data_ = *data;
     67       }
     68       source_.Get(key, *fresh_data_ready_);
     69     }
     70     delete data;
     71   }
     72 
     73   void OnFreshDataReady(bool success,
     74                         const std::string& key,
     75                         std::string* data) {
     76     if (success) {
     77       assert(data != NULL);
     78       retrieved_(true, key, *data);
     79       storage_->Put(key, data);
     80       data = NULL;  // Deleted by Storage::Put().
     81     } else if (!stale_data_.empty()) {
     82       // Reuse the stale data if a download fails. It's better to have slightly
     83       // outdated validation rules than to suddenly lose validation ability.
     84       retrieved_(true, key, stale_data_);
     85     } else {
     86       retrieved_(false, key, std::string());
     87     }
     88     delete data;
     89     delete this;
     90   }
     91 
     92   const Retriever::Callback& retrieved_;
     93   const Source& source_;
     94   ValidatingStorage* storage_;
     95   const scoped_ptr<const Source::Callback> fresh_data_ready_;
     96   const scoped_ptr<const Storage::Callback> validated_data_ready_;
     97   std::string stale_data_;
     98 
     99   DISALLOW_COPY_AND_ASSIGN(Helper);
    100 };
    101 
    102 }  // namespace
    103 
    104 Retriever::Retriever(const Source* source, Storage* storage)
    105     : source_(source), storage_(new ValidatingStorage(storage)) {
    106   assert(source_ != NULL);
    107   assert(storage_ != NULL);
    108 }
    109 
    110 Retriever::~Retriever() {}
    111 
    112 void Retriever::Retrieve(const std::string& key,
    113                          const Callback& retrieved) const {
    114   new Helper(key, retrieved, *source_, storage_.get());
    115 }
    116 
    117 }  // namespace addressinput
    118 }  // namespace i18n
    119