1// Copyright (C) 2014 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 <libaddressinput/address_normalizer.h> 16 17#include <libaddressinput/address_data.h> 18#include <libaddressinput/address_field.h> 19#include <libaddressinput/preload_supplier.h> 20 21#include <cassert> 22#include <cstddef> 23#include <string> 24#include <vector> 25 26#include "lookup_key.h" 27#include "rule.h" 28#include "util/string_compare.h" 29 30namespace i18n { 31namespace addressinput { 32 33AddressNormalizer::AddressNormalizer(const PreloadSupplier* supplier) 34 : supplier_(supplier), 35 compare_(new StringCompare) { 36 assert(supplier_ != NULL); 37} 38 39AddressNormalizer::~AddressNormalizer() {} 40 41void AddressNormalizer::Normalize(AddressData* address) const { 42 assert(address != NULL); 43 assert(supplier_->IsLoaded(address->region_code)); 44 45 AddressData region_address; 46 region_address.region_code = address->region_code; 47 LookupKey parent_key; 48 parent_key.FromAddress(region_address); 49 const Rule* parent_rule = supplier_->GetRule(parent_key); 50 assert(parent_rule != NULL); 51 52 LookupKey lookup_key; 53 for (size_t depth = 1; depth < arraysize(LookupKey::kHierarchy); ++depth) { 54 AddressField field = LookupKey::kHierarchy[depth]; 55 if (address->IsFieldEmpty(field)) { 56 return; 57 } 58 const std::string& field_value = address->GetFieldValue(field); 59 bool no_match_found_yet = true; 60 for (std::vector<std::string>::const_iterator 61 key_it = parent_rule->GetSubKeys().begin(); 62 key_it != parent_rule->GetSubKeys().end(); ++key_it) { 63 lookup_key.FromLookupKey(parent_key, *key_it); 64 const Rule* rule = supplier_->GetRule(lookup_key); 65 assert(rule != NULL); 66 67 bool matches_latin_name = 68 compare_->NaturalEquals(field_value, rule->GetLatinName()); 69 bool matches_local_name_id = 70 compare_->NaturalEquals(field_value, *key_it) || 71 compare_->NaturalEquals(field_value, rule->GetName()); 72 if (matches_latin_name || matches_local_name_id) { 73 address->SetFieldValue( 74 field, matches_latin_name ? rule->GetLatinName() : *key_it); 75 no_match_found_yet = false; 76 parent_key.FromLookupKey(parent_key, *key_it); 77 parent_rule = supplier_->GetRule(parent_key); 78 assert(parent_rule != NULL); 79 break; 80 } 81 } 82 if (no_match_found_yet) { 83 return; // Abort search. 84 } 85 } 86} 87 88} // namespace addressinput 89} // namespace i18n 90