1e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com// Copyright (C) 2014 Google Inc.
2e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com//
3e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com// Licensed under the Apache License, Version 2.0 (the "License");
4e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com// you may not use this file except in compliance with the License.
5e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com// You may obtain a copy of the License at
6e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com//
7e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com// http://www.apache.org/licenses/LICENSE-2.0
8e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com//
9e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com// Unless required by applicable law or agreed to in writing, software
10e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com// distributed under the License is distributed on an "AS IS" BASIS,
11e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com// See the License for the specific language governing permissions and
13e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com// limitations under the License.
14e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com
15e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com#include <libaddressinput/address_data.h>
16e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com
17e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com#include <libaddressinput/address_field.h>
18e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com#include <libaddressinput/util/basictypes.h>
19e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com
20e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com#include <algorithm>
21e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com#include <cassert>
22e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com#include <cstddef>
23e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com#include <functional>
246e459a252dbfcce8411911ee38e68884c9e96887lararennie@google.com#include <ostream>
25e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com#include <string>
26e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com#include <vector>
27e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com
28ea5e77397b59d94af3591644c3dc23dc6f9ba22eroubert@google.com#include <re2/re2.h>
29ea5e77397b59d94af3591644c3dc23dc6f9ba22eroubert@google.com
30e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.comnamespace i18n {
31e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.comnamespace addressinput {
32e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com
33e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.comnamespace {
34e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com
35e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com// Mapping from AddressField value to pointer to AddressData member.
362fbc3617221414ff659533aaf8033526443b3773rouslan@chromium.orgstd::string AddressData::*kStringField[] = {
37e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com  &AddressData::region_code,
38e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com  &AddressData::administrative_area,
39e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com  &AddressData::locality,
40e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com  &AddressData::dependent_locality,
41e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com  &AddressData::sorting_code,
42e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com  &AddressData::postal_code,
43e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com  NULL,
44b52a2aeb63a28914850f3ed81cd7fd26ecdd4cdcrouslan@chromium.org  &AddressData::organization,
45e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com  &AddressData::recipient
46e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com};
47e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com
48e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com// Mapping from AddressField value to pointer to AddressData member.
49e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.comconst std::vector<std::string> AddressData::*kVectorStringField[] = {
50e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com  NULL,
51e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com  NULL,
52e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com  NULL,
53e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com  NULL,
54e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com  NULL,
55e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com  NULL,
56e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com  &AddressData::address_line,
57b52a2aeb63a28914850f3ed81cd7fd26ecdd4cdcrouslan@chromium.org  NULL,
58e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com  NULL
59e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com};
60e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com
61e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.comCOMPILE_ASSERT(arraysize(kStringField) == arraysize(kVectorStringField),
62e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com               field_mapping_array_size_mismatch);
63e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com
64ff5a4a63b5a4c5f1ffc1049d2ea7449d4794e9a7roubert@google.com// A string is considered to be "empty" not only if it actually is empty, but
65ff5a4a63b5a4c5f1ffc1049d2ea7449d4794e9a7roubert@google.com// also if it contains nothing but whitespace.
66ff5a4a63b5a4c5f1ffc1049d2ea7449d4794e9a7roubert@google.combool IsStringEmpty(const std::string& str) {
67ff5a4a63b5a4c5f1ffc1049d2ea7449d4794e9a7roubert@google.com  static const RE2 kMatcher("\\S");
68ff5a4a63b5a4c5f1ffc1049d2ea7449d4794e9a7roubert@google.com  return str.empty() || !RE2::PartialMatch(str, kMatcher);
69ff5a4a63b5a4c5f1ffc1049d2ea7449d4794e9a7roubert@google.com}
70ff5a4a63b5a4c5f1ffc1049d2ea7449d4794e9a7roubert@google.com
71e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com}  // namespace
72e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com
73e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.combool AddressData::IsFieldEmpty(AddressField field) const {
74e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com  assert(field >= 0);
75e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com  assert(static_cast<size_t>(field) < arraysize(kStringField));
76e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com  if (kStringField[field] != NULL) {
77e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com    const std::string& value = GetFieldValue(field);
78ff5a4a63b5a4c5f1ffc1049d2ea7449d4794e9a7roubert@google.com    return IsStringEmpty(value);
79e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com  } else {
80e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com    const std::vector<std::string>& value = GetRepeatedFieldValue(field);
81000aa6dbb70273ccefa77a5d4cd1a400939a2666roubert@google.com    return std::find_if(value.begin(),
82000aa6dbb70273ccefa77a5d4cd1a400939a2666roubert@google.com                        value.end(),
83000aa6dbb70273ccefa77a5d4cd1a400939a2666roubert@google.com                        std::not1(std::ptr_fun(&IsStringEmpty))) == value.end();
84e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com  }
85e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com}
86e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com
87e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.comconst std::string& AddressData::GetFieldValue(
88e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com    AddressField field) const {
89e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com  assert(field >= 0);
90e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com  assert(static_cast<size_t>(field) < arraysize(kStringField));
91e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com  assert(kStringField[field] != NULL);
92e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com  return this->*kStringField[field];
93e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com}
94e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com
952fbc3617221414ff659533aaf8033526443b3773rouslan@chromium.orgvoid AddressData::SetFieldValue(AddressField field, const std::string& value) {
962fbc3617221414ff659533aaf8033526443b3773rouslan@chromium.org  assert(field >= 0);
972fbc3617221414ff659533aaf8033526443b3773rouslan@chromium.org  assert(static_cast<size_t>(field) < arraysize(kStringField));
982fbc3617221414ff659533aaf8033526443b3773rouslan@chromium.org  assert(kStringField[field] != NULL);
992fbc3617221414ff659533aaf8033526443b3773rouslan@chromium.org  (this->*kStringField[field]).assign(value);
1002fbc3617221414ff659533aaf8033526443b3773rouslan@chromium.org}
1012fbc3617221414ff659533aaf8033526443b3773rouslan@chromium.org
102e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.comconst std::vector<std::string>& AddressData::GetRepeatedFieldValue(
103e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com    AddressField field) const {
104b61f18aac9eba56eff3bae712371924567f89d15roubert@google.com  assert(IsRepeatedFieldValue(field));
105e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com  return this->*kVectorStringField[field];
106e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com}
107e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com
1086e459a252dbfcce8411911ee38e68884c9e96887lararennie@google.combool AddressData::operator==(const AddressData& other) const {
109000aa6dbb70273ccefa77a5d4cd1a400939a2666roubert@google.com  return region_code == other.region_code &&
110000aa6dbb70273ccefa77a5d4cd1a400939a2666roubert@google.com         address_line == other.address_line &&
111000aa6dbb70273ccefa77a5d4cd1a400939a2666roubert@google.com         administrative_area == other.administrative_area &&
112000aa6dbb70273ccefa77a5d4cd1a400939a2666roubert@google.com         locality == other.locality &&
113000aa6dbb70273ccefa77a5d4cd1a400939a2666roubert@google.com         dependent_locality == other.dependent_locality &&
114000aa6dbb70273ccefa77a5d4cd1a400939a2666roubert@google.com         postal_code == other.postal_code &&
115000aa6dbb70273ccefa77a5d4cd1a400939a2666roubert@google.com         sorting_code == other.sorting_code &&
116b52a2aeb63a28914850f3ed81cd7fd26ecdd4cdcrouslan@chromium.org         language_code == other.language_code &&
117b52a2aeb63a28914850f3ed81cd7fd26ecdd4cdcrouslan@chromium.org         organization == other.organization &&
118b52a2aeb63a28914850f3ed81cd7fd26ecdd4cdcrouslan@chromium.org         recipient == other.recipient;
1196e459a252dbfcce8411911ee38e68884c9e96887lararennie@google.com}
1206e459a252dbfcce8411911ee38e68884c9e96887lararennie@google.com
121e66bf12636bf12067bd8b199b8e6c1035315d2aakeghani@google.com// static
122e66bf12636bf12067bd8b199b8e6c1035315d2aakeghani@google.combool AddressData::IsRepeatedFieldValue(AddressField field) {
123b61f18aac9eba56eff3bae712371924567f89d15roubert@google.com  assert(field >= 0);
124b61f18aac9eba56eff3bae712371924567f89d15roubert@google.com  assert(static_cast<size_t>(field) < arraysize(kVectorStringField));
125b61f18aac9eba56eff3bae712371924567f89d15roubert@google.com  return kVectorStringField[field] != NULL;
126e66bf12636bf12067bd8b199b8e6c1035315d2aakeghani@google.com}
127e66bf12636bf12067bd8b199b8e6c1035315d2aakeghani@google.com
128e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com}  // namespace addressinput
129e0cd6d6862db732f3fd035cdebd3a5d0ee8701c7roubert@google.com}  // namespace i18n
1306e459a252dbfcce8411911ee38e68884c9e96887lararennie@google.com
1316e459a252dbfcce8411911ee38e68884c9e96887lararennie@google.comstd::ostream& operator<<(std::ostream& o,
1326e459a252dbfcce8411911ee38e68884c9e96887lararennie@google.com                         const i18n::addressinput::AddressData& address) {
1336e459a252dbfcce8411911ee38e68884c9e96887lararennie@google.com  o << "region_code: \"" << address.region_code << "\"\n"
1346e459a252dbfcce8411911ee38e68884c9e96887lararennie@google.com    "administrative_area: \"" << address.administrative_area << "\"\n"
1356e459a252dbfcce8411911ee38e68884c9e96887lararennie@google.com    "locality: \"" << address.locality << "\"\n"
1366e459a252dbfcce8411911ee38e68884c9e96887lararennie@google.com    "dependent_locality: \"" << address.dependent_locality << "\"\n"
1376e459a252dbfcce8411911ee38e68884c9e96887lararennie@google.com    "postal_code: \"" << address.postal_code << "\"\n"
1386e459a252dbfcce8411911ee38e68884c9e96887lararennie@google.com    "sorting_code: \"" << address.sorting_code << "\"\n";
1396e459a252dbfcce8411911ee38e68884c9e96887lararennie@google.com
1406e459a252dbfcce8411911ee38e68884c9e96887lararennie@google.com  // TODO: Update the field order in the .h file to match the order they are
1416e459a252dbfcce8411911ee38e68884c9e96887lararennie@google.com  // printed out here, for consistency.
1426e459a252dbfcce8411911ee38e68884c9e96887lararennie@google.com  for (std::vector<std::string>::const_iterator it =
1436e459a252dbfcce8411911ee38e68884c9e96887lararennie@google.com           address.address_line.begin();
1446e459a252dbfcce8411911ee38e68884c9e96887lararennie@google.com       it != address.address_line.end(); ++it) {
1456e459a252dbfcce8411911ee38e68884c9e96887lararennie@google.com    o << "address_line: \"" << *it << "\"\n";
1466e459a252dbfcce8411911ee38e68884c9e96887lararennie@google.com  }
1476e459a252dbfcce8411911ee38e68884c9e96887lararennie@google.com
1486e459a252dbfcce8411911ee38e68884c9e96887lararennie@google.com  o << "language_code: \"" << address.language_code << "\"\n"
149b52a2aeb63a28914850f3ed81cd7fd26ecdd4cdcrouslan@chromium.org    "organization: \"" << address.organization << "\"\n"
1506e459a252dbfcce8411911ee38e68884c9e96887lararennie@google.com    "recipient: \"" << address.recipient << "\"\n";
1516e459a252dbfcce8411911ee38e68884c9e96887lararennie@google.com
1526e459a252dbfcce8411911ee38e68884c9e96887lararennie@google.com  return o;
1536e459a252dbfcce8411911ee38e68884c9e96887lararennie@google.com}
154