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 <libaddressinput/address_data.h> 16 17 #include <libaddressinput/address_field.h> 18 19 #include <algorithm> 20 #include <cassert> 21 #include <cstddef> 22 #include <string> 23 #include <vector> 24 25 #include "region_data_constants.h" 26 #include "rule.h" 27 #include "util/string_util.h" 28 29 namespace i18n { 30 namespace addressinput { 31 32 namespace { 33 34 const std::string* GetMemberForField(const AddressData& address, 35 AddressField field) { 36 switch (field) { 37 case COUNTRY: 38 return &address.country_code; 39 case ADMIN_AREA: 40 return &address.administrative_area; 41 case LOCALITY: 42 return &address.locality; 43 case DEPENDENT_LOCALITY: 44 return &address.dependent_locality; 45 case SORTING_CODE: 46 return &address.sorting_code; 47 case POSTAL_CODE: 48 return &address.postal_code; 49 case ORGANIZATION: 50 return &address.organization; 51 case RECIPIENT: 52 return &address.recipient; 53 case STREET_ADDRESS: 54 break; 55 } 56 57 assert(false); 58 return NULL; 59 } 60 61 } // namespace 62 63 void AddressData::FormatForDisplay(std::vector<std::string>* lines) const { 64 assert(lines != NULL); 65 lines->clear(); 66 67 Rule rule; 68 rule.CopyFrom(Rule::GetDefault()); 69 rule.ParseSerializedRule(RegionDataConstants::GetRegionData(country_code)); 70 71 // If latinized rules are available and the |language_code| of this address is 72 // not the primary language code for the region, then use the latinized 73 // formatting rules. 74 const std::vector<std::vector<FormatElement> >& format = 75 rule.GetLatinFormat().empty() || 76 language_code.empty() || 77 NormalizeLanguageCode(language_code) == 78 NormalizeLanguageCode(rule.GetLanguage()) 79 ? rule.GetFormat() : rule.GetLatinFormat(); 80 81 for (size_t i = 0; i < format.size(); ++i) { 82 std::string line; 83 for (size_t j = 0; j < format[i].size(); ++j) { 84 const FormatElement& element = format[i][j]; 85 if (element.IsField()) { 86 if (element.field == STREET_ADDRESS) { 87 // Street address field can contain multiple values. 88 for (size_t k = 0; k < address_lines.size(); ++k) { 89 line += address_lines[k]; 90 if (k < address_lines.size() - 1) { 91 lines->push_back(line); 92 line.clear(); 93 } 94 } 95 } else { 96 line += GetFieldValue(element.field); 97 } 98 } else { 99 line += element.literal; 100 } 101 } 102 103 if (!line.empty()) { 104 lines->push_back(line); 105 } 106 } 107 } 108 109 const std::string& AddressData::GetFieldValue(AddressField field) const { 110 const std::string* field_value = GetMemberForField(*this, field); 111 return field_value != NULL ? *field_value : country_code; 112 } 113 114 void AddressData::SetFieldValue(AddressField field, const std::string& value) { 115 std::string* field_value = 116 const_cast<std::string*>(GetMemberForField(*this, field)); 117 if (field_value != NULL) { 118 *field_value = value; 119 } 120 } 121 122 bool AddressData::HasAllRequiredFields() const { 123 if (country_code.empty()) 124 return false; 125 126 Rule rule; 127 rule.CopyFrom(Rule::GetDefault()); 128 if (!rule.ParseSerializedRule( 129 RegionDataConstants::GetRegionData(country_code))) { 130 return false; 131 } 132 133 std::vector< ::i18n::addressinput::AddressField> required_fields = 134 rule.GetRequired(); 135 for (size_t i = 0; i < required_fields.size(); ++i) { 136 if (required_fields[i] == STREET_ADDRESS) { 137 if (address_lines.empty() || address_lines[0].empty()) { 138 return false; 139 } 140 } else if (GetFieldValue(required_fields[i]).empty()) { 141 return false; 142 } 143 } 144 145 return true; 146 } 147 148 } // namespace addressinput 149 } // namespace i18n 150