• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "annotator/types.h"
18 
19 #include <vector>
20 
21 #include "utils/optional.h"
22 
23 namespace libtextclassifier3 {
24 
operator <<(logging::LoggingStringStream & stream,const Token & token)25 logging::LoggingStringStream& operator<<(logging::LoggingStringStream& stream,
26                                          const Token& token) {
27   if (!token.is_padding) {
28     return stream << "Token(\"" << token.value << "\", " << token.start << ", "
29                   << token.end << ")";
30   } else {
31     return stream << "Token()";
32   }
33 }
34 
ShouldRoundToGranularity() const35 bool DatetimeComponent::ShouldRoundToGranularity() const {
36   // Don't round to the granularity for relative expressions that specify the
37   // distance. So that, e.g. "in 2 hours" when it's 8:35:03 will result in
38   // 10:35:03.
39   if (relative_qualifier == RelativeQualifier::UNSPECIFIED) {
40     return false;
41   }
42   if (relative_qualifier == RelativeQualifier::NEXT ||
43       relative_qualifier == RelativeQualifier::TOMORROW ||
44       relative_qualifier == RelativeQualifier::YESTERDAY ||
45       relative_qualifier == RelativeQualifier::LAST ||
46       relative_qualifier == RelativeQualifier::THIS ||
47       relative_qualifier == RelativeQualifier::NOW) {
48     return true;
49   }
50   return false;
51 }
52 
53 namespace {
FormatMillis(int64 time_ms_utc)54 std::string FormatMillis(int64 time_ms_utc) {
55   long time_seconds = time_ms_utc / 1000;  // NOLINT
56   char buffer[512];
57   strftime(buffer, sizeof(buffer), "%a %Y-%m-%d %H:%M:%S %Z",
58            localtime(&time_seconds));
59   return std::string(buffer);
60 }
61 }  // namespace
62 
ComponentTypeToString(const DatetimeComponent::ComponentType & component_type)63 std::string ComponentTypeToString(
64     const DatetimeComponent::ComponentType& component_type) {
65   switch (component_type) {
66     case DatetimeComponent::ComponentType::UNSPECIFIED:
67       return "UNSPECIFIED";
68     case DatetimeComponent::ComponentType::YEAR:
69       return "YEAR";
70     case DatetimeComponent::ComponentType::MONTH:
71       return "MONTH";
72     case DatetimeComponent::ComponentType::WEEK:
73       return "WEEK";
74     case DatetimeComponent::ComponentType::DAY_OF_WEEK:
75       return "DAY_OF_WEEK";
76     case DatetimeComponent::ComponentType::DAY_OF_MONTH:
77       return "DAY_OF_MONTH";
78     case DatetimeComponent::ComponentType::HOUR:
79       return "HOUR";
80     case DatetimeComponent::ComponentType::MINUTE:
81       return "MINUTE";
82     case DatetimeComponent::ComponentType::SECOND:
83       return "SECOND";
84     case DatetimeComponent::ComponentType::MERIDIEM:
85       return "MERIDIEM";
86     case DatetimeComponent::ComponentType::ZONE_OFFSET:
87       return "ZONE_OFFSET";
88     case DatetimeComponent::ComponentType::DST_OFFSET:
89       return "DST_OFFSET";
90     default:
91       return "";
92   }
93 }
94 
RelativeQualifierToString(const DatetimeComponent::RelativeQualifier & relative_qualifier)95 std::string RelativeQualifierToString(
96     const DatetimeComponent::RelativeQualifier& relative_qualifier) {
97   switch (relative_qualifier) {
98     case DatetimeComponent::RelativeQualifier::UNSPECIFIED:
99       return "UNSPECIFIED";
100     case DatetimeComponent::RelativeQualifier::NEXT:
101       return "NEXT";
102     case DatetimeComponent::RelativeQualifier::THIS:
103       return "THIS";
104     case DatetimeComponent::RelativeQualifier::LAST:
105       return "LAST";
106     case DatetimeComponent::RelativeQualifier::NOW:
107       return "NOW";
108     case DatetimeComponent::RelativeQualifier::TOMORROW:
109       return "TOMORROW";
110     case DatetimeComponent::RelativeQualifier::YESTERDAY:
111       return "YESTERDAY";
112     case DatetimeComponent::RelativeQualifier::PAST:
113       return "PAST";
114     case DatetimeComponent::RelativeQualifier::FUTURE:
115       return "FUTURE";
116     default:
117       return "";
118   }
119 }
120 
operator <<(logging::LoggingStringStream & stream,const DatetimeParseResultSpan & value)121 logging::LoggingStringStream& operator<<(logging::LoggingStringStream& stream,
122                                          const DatetimeParseResultSpan& value) {
123   stream << "DatetimeParseResultSpan({" << value.span.first << ", "
124          << value.span.second << "}, "
125          << "/*target_classification_score=*/ "
126          << value.target_classification_score << "/*priority_score=*/"
127          << value.priority_score << " {";
128   for (const DatetimeParseResult& data : value.data) {
129     stream << "{/*time_ms_utc=*/ " << data.time_ms_utc << " /* "
130            << FormatMillis(data.time_ms_utc) << " */, /*granularity=*/ "
131            << data.granularity << ", /*datetime_components=*/ ";
132     for (const DatetimeComponent& datetime_comp : data.datetime_components) {
133       stream << "{/*component_type=*/ "
134              << ComponentTypeToString(datetime_comp.component_type)
135              << " /*relative_qualifier=*/ "
136              << RelativeQualifierToString(datetime_comp.relative_qualifier)
137              << " /*value=*/ " << datetime_comp.value << " /*relative_count=*/ "
138              << datetime_comp.relative_count << "}, ";
139     }
140     stream << "}, ";
141   }
142   stream << "})";
143   return stream;
144 }
145 
operator ==(const ClassificationResult & other) const146 bool ClassificationResult::operator==(const ClassificationResult& other) const {
147   return ClassificationResultsEqualIgnoringScoresAndSerializedEntityData(
148              *this, other) &&
149          fabs(score - other.score) < 0.001 &&
150          fabs(priority_score - other.priority_score) < 0.001 &&
151          serialized_entity_data == other.serialized_entity_data;
152 }
153 
ClassificationResultsEqualIgnoringScoresAndSerializedEntityData(const ClassificationResult & a,const ClassificationResult & b)154 bool ClassificationResultsEqualIgnoringScoresAndSerializedEntityData(
155     const ClassificationResult& a, const ClassificationResult& b) {
156   return a.collection == b.collection &&
157          a.datetime_parse_result == b.datetime_parse_result &&
158          a.serialized_knowledge_result == b.serialized_knowledge_result &&
159          a.contact_pointer == b.contact_pointer &&
160          a.contact_name == b.contact_name &&
161          a.contact_given_name == b.contact_given_name &&
162          a.contact_family_name == b.contact_family_name &&
163          a.contact_nickname == b.contact_nickname &&
164          a.contact_email_address == b.contact_email_address &&
165          a.contact_phone_number == b.contact_phone_number &&
166          a.contact_id == b.contact_id &&
167          a.app_package_name == b.app_package_name &&
168          a.numeric_value == b.numeric_value &&
169          fabs(a.numeric_double_value - b.numeric_double_value) < 0.001 &&
170          a.duration_ms == b.duration_ms;
171 }
172 
operator <<(logging::LoggingStringStream & stream,const ClassificationResult & result)173 logging::LoggingStringStream& operator<<(logging::LoggingStringStream& stream,
174                                          const ClassificationResult& result) {
175   return stream << "ClassificationResult(" << result.collection
176                 << ", /*score=*/ " << result.score << ", /*priority_score=*/ "
177                 << result.priority_score << ")";
178 }
179 
operator <<(logging::LoggingStringStream & stream,const std::vector<ClassificationResult> & results)180 logging::LoggingStringStream& operator<<(
181     logging::LoggingStringStream& stream,
182     const std::vector<ClassificationResult>& results) {
183   stream = stream << "{\n";
184   for (const ClassificationResult& result : results) {
185     stream = stream << "    " << result << "\n";
186   }
187   stream = stream << "}";
188   return stream;
189 }
190 
operator <<(logging::LoggingStringStream & stream,const AnnotatedSpan & span)191 logging::LoggingStringStream& operator<<(logging::LoggingStringStream& stream,
192                                          const AnnotatedSpan& span) {
193   std::string best_class;
194   float best_score = -1;
195   if (!span.classification.empty()) {
196     best_class = span.classification[0].collection;
197     best_score = span.classification[0].score;
198   }
199   return stream << "Span(" << span.span.first << ", " << span.span.second
200                 << ", " << best_class << ", " << best_score << ")";
201 }
202 
operator <<(logging::LoggingStringStream & stream,const DatetimeParsedData & data)203 logging::LoggingStringStream& operator<<(logging::LoggingStringStream& stream,
204                                          const DatetimeParsedData& data) {
205   std::vector<DatetimeComponent> date_time_components;
206   data.GetDatetimeComponents(&date_time_components);
207   stream = stream << "DatetimeParsedData { \n";
208   for (const DatetimeComponent& c : date_time_components) {
209     stream = stream << " DatetimeComponent { \n";
210     stream = stream << "  Component Type:" << static_cast<int>(c.component_type)
211                     << "\n";
212     stream = stream << "  Value:" << c.value << "\n";
213     stream = stream << "  Relative Qualifier:"
214                     << static_cast<int>(c.relative_qualifier) << "\n";
215     stream = stream << "  Relative Count:" << c.relative_count << "\n";
216     stream = stream << " } \n";
217   }
218   stream = stream << "}";
219   return stream;
220 }
221 
SetAbsoluteValue(const DatetimeComponent::ComponentType & field_type,int value)222 void DatetimeParsedData::SetAbsoluteValue(
223     const DatetimeComponent::ComponentType& field_type, int value) {
224   GetOrCreateDatetimeComponent(field_type).value = value;
225 }
226 
SetRelativeValue(const DatetimeComponent::ComponentType & field_type,const DatetimeComponent::RelativeQualifier & relative_value)227 void DatetimeParsedData::SetRelativeValue(
228     const DatetimeComponent::ComponentType& field_type,
229     const DatetimeComponent::RelativeQualifier& relative_value) {
230   GetOrCreateDatetimeComponent(field_type).relative_qualifier = relative_value;
231 }
232 
SetRelativeCount(const DatetimeComponent::ComponentType & field_type,int relative_count)233 void DatetimeParsedData::SetRelativeCount(
234     const DatetimeComponent::ComponentType& field_type, int relative_count) {
235   GetOrCreateDatetimeComponent(field_type).relative_count = relative_count;
236 }
237 
AddDatetimeComponents(const std::vector<DatetimeComponent> & datetime_components)238 void DatetimeParsedData::AddDatetimeComponents(
239     const std::vector<DatetimeComponent>& datetime_components) {
240   for (const DatetimeComponent& datetime_component : datetime_components) {
241     date_time_components_.insert(
242         {datetime_component.component_type, datetime_component});
243   }
244 }
245 
HasFieldType(const DatetimeComponent::ComponentType & field_type) const246 bool DatetimeParsedData::HasFieldType(
247     const DatetimeComponent::ComponentType& field_type) const {
248   if (date_time_components_.find(field_type) == date_time_components_.end()) {
249     return false;
250   }
251   return true;
252 }
253 
GetFieldValue(const DatetimeComponent::ComponentType & field_type,int * field_value) const254 bool DatetimeParsedData::GetFieldValue(
255     const DatetimeComponent::ComponentType& field_type,
256     int* field_value) const {
257   if (HasFieldType(field_type)) {
258     *field_value = date_time_components_.at(field_type).value;
259     return true;
260   }
261   return false;
262 }
263 
GetRelativeValue(const DatetimeComponent::ComponentType & field_type,DatetimeComponent::RelativeQualifier * relative_value) const264 bool DatetimeParsedData::GetRelativeValue(
265     const DatetimeComponent::ComponentType& field_type,
266     DatetimeComponent::RelativeQualifier* relative_value) const {
267   if (HasFieldType(field_type)) {
268     *relative_value = date_time_components_.at(field_type).relative_qualifier;
269     return true;
270   }
271   return false;
272 }
273 
HasRelativeValue(const DatetimeComponent::ComponentType & field_type) const274 bool DatetimeParsedData::HasRelativeValue(
275     const DatetimeComponent::ComponentType& field_type) const {
276   if (HasFieldType(field_type)) {
277     return date_time_components_.at(field_type).relative_qualifier !=
278            DatetimeComponent::RelativeQualifier::UNSPECIFIED;
279   }
280   return false;
281 }
282 
HasAbsoluteValue(const DatetimeComponent::ComponentType & field_type) const283 bool DatetimeParsedData::HasAbsoluteValue(
284     const DatetimeComponent::ComponentType& field_type) const {
285   return HasFieldType(field_type) && !HasRelativeValue(field_type);
286 }
287 
IsEmpty() const288 bool DatetimeParsedData::IsEmpty() const {
289   return date_time_components_.empty();
290 }
291 
GetRelativeDatetimeComponents(std::vector<DatetimeComponent> * date_time_components) const292 void DatetimeParsedData::GetRelativeDatetimeComponents(
293     std::vector<DatetimeComponent>* date_time_components) const {
294   for (auto it = date_time_components_.begin();
295        it != date_time_components_.end(); it++) {
296     if (it->second.relative_qualifier !=
297         DatetimeComponent::RelativeQualifier::UNSPECIFIED) {
298       date_time_components->push_back(it->second);
299     }
300   }
301 }
302 
GetDatetimeComponents(std::vector<DatetimeComponent> * date_time_components) const303 void DatetimeParsedData::GetDatetimeComponents(
304     std::vector<DatetimeComponent>* date_time_components) const {
305   for (auto it = date_time_components_.begin();
306        it != date_time_components_.end(); it++) {
307     date_time_components->push_back(it->second);
308   }
309 }
310 
GetOrCreateDatetimeComponent(const DatetimeComponent::ComponentType & component_type)311 DatetimeComponent& DatetimeParsedData::GetOrCreateDatetimeComponent(
312     const DatetimeComponent::ComponentType& component_type) {
313   auto result =
314       date_time_components_
315           .insert(
316               {component_type,
317                DatetimeComponent(
318                    component_type,
319                    DatetimeComponent::RelativeQualifier::UNSPECIFIED, 0, 0)})
320           .first;
321   return result->second;
322 }
323 
324 namespace {
GetFinestGranularityFromComponentTypes(const std::vector<DatetimeComponent::ComponentType> & datetime_component_types)325 DatetimeGranularity GetFinestGranularityFromComponentTypes(
326     const std::vector<DatetimeComponent::ComponentType>&
327         datetime_component_types) {
328   DatetimeGranularity granularity = DatetimeGranularity::GRANULARITY_UNKNOWN;
329   for (const auto& component_type : datetime_component_types) {
330     switch (component_type) {
331       case DatetimeComponent::ComponentType::YEAR:
332         if (granularity < DatetimeGranularity::GRANULARITY_YEAR) {
333           granularity = DatetimeGranularity::GRANULARITY_YEAR;
334         }
335         break;
336 
337       case DatetimeComponent::ComponentType::MONTH:
338         if (granularity < DatetimeGranularity::GRANULARITY_MONTH) {
339           granularity = DatetimeGranularity::GRANULARITY_MONTH;
340         }
341         break;
342 
343       case DatetimeComponent::ComponentType::WEEK:
344         if (granularity < DatetimeGranularity::GRANULARITY_WEEK) {
345           granularity = DatetimeGranularity::GRANULARITY_WEEK;
346         }
347         break;
348 
349       case DatetimeComponent::ComponentType::DAY_OF_WEEK:
350       case DatetimeComponent::ComponentType::DAY_OF_MONTH:
351         if (granularity < DatetimeGranularity::GRANULARITY_DAY) {
352           granularity = DatetimeGranularity::GRANULARITY_DAY;
353         }
354         break;
355 
356       case DatetimeComponent::ComponentType::HOUR:
357         if (granularity < DatetimeGranularity::GRANULARITY_HOUR) {
358           granularity = DatetimeGranularity::GRANULARITY_HOUR;
359         }
360         break;
361 
362       case DatetimeComponent::ComponentType::MINUTE:
363         if (granularity < DatetimeGranularity::GRANULARITY_MINUTE) {
364           granularity = DatetimeGranularity::GRANULARITY_MINUTE;
365         }
366         break;
367 
368       case DatetimeComponent::ComponentType::SECOND:
369         if (granularity < DatetimeGranularity::GRANULARITY_SECOND) {
370           granularity = DatetimeGranularity::GRANULARITY_SECOND;
371         }
372         break;
373 
374       case DatetimeComponent::ComponentType::MERIDIEM:
375       case DatetimeComponent::ComponentType::ZONE_OFFSET:
376       case DatetimeComponent::ComponentType::DST_OFFSET:
377       default:
378         break;
379     }
380   }
381   return granularity;
382 }
383 }  // namespace
384 
GetFinestGranularity() const385 DatetimeGranularity DatetimeParsedData::GetFinestGranularity() const {
386   std::vector<DatetimeComponent::ComponentType> component_types;
387   std::transform(date_time_components_.begin(), date_time_components_.end(),
388                  std::back_inserter(component_types),
389                  [](const std::map<DatetimeComponent::ComponentType,
390                                    DatetimeComponent>::value_type& pair) {
391                    return pair.first;
392                  });
393   return GetFinestGranularityFromComponentTypes(component_types);
394 }
395 
GetDatetimeComponent(const std::vector<DatetimeComponent> & datetime_components,const DatetimeComponent::ComponentType & component_type)396 Optional<DatetimeComponent> GetDatetimeComponent(
397     const std::vector<DatetimeComponent>& datetime_components,
398     const DatetimeComponent::ComponentType& component_type) {
399   for (auto datetime_component : datetime_components) {
400     if (datetime_component.component_type == component_type) {
401       return Optional<DatetimeComponent>(datetime_component);
402     }
403   }
404   return Optional<DatetimeComponent>();
405 }
406 
407 // Returns the granularity of the DatetimeComponents.
GetFinestGranularity(const std::vector<DatetimeComponent> & datetime_component)408 DatetimeGranularity GetFinestGranularity(
409     const std::vector<DatetimeComponent>& datetime_component) {
410   std::vector<DatetimeComponent::ComponentType> component_types;
411   std::transform(datetime_component.begin(), datetime_component.end(),
412                  std::back_inserter(component_types),
413                  [](const DatetimeComponent& component) {
414                    return component.component_type;
415                  });
416   return GetFinestGranularityFromComponentTypes(component_types);
417 }
418 
419 }  // namespace libtextclassifier3
420