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