• 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 "actions/utils.h"
18 
19 #include "annotator/collections.h"
20 #include "utils/base/logging.h"
21 #include "utils/normalization.h"
22 #include "utils/strings/stringpiece.h"
23 
24 namespace libtextclassifier3 {
25 
26 // Name for a datetime annotation that only includes time but no date.
27 const std::string& kTimeAnnotation =
__anon323323a30102() 28     *[]() { return new std::string("time"); }();
29 
FillSuggestionFromSpec(const ActionSuggestionSpec * action,MutableFlatbuffer * entity_data,ActionSuggestion * suggestion)30 void FillSuggestionFromSpec(const ActionSuggestionSpec* action,
31                             MutableFlatbuffer* entity_data,
32                             ActionSuggestion* suggestion) {
33   if (action != nullptr) {
34     suggestion->score = action->score();
35     suggestion->priority_score = action->priority_score();
36     if (action->type() != nullptr) {
37       suggestion->type = action->type()->str();
38     }
39     if (action->response_text() != nullptr) {
40       suggestion->response_text = action->response_text()->str();
41     }
42     if (action->serialized_entity_data() != nullptr) {
43       TC3_CHECK_NE(entity_data, nullptr);
44       entity_data->MergeFromSerializedFlatbuffer(
45           StringPiece(action->serialized_entity_data()->data(),
46                       action->serialized_entity_data()->size()));
47     }
48     if (action->entity_data() != nullptr) {
49       TC3_CHECK_NE(entity_data, nullptr);
50       entity_data->MergeFrom(
51           reinterpret_cast<const flatbuffers::Table*>(action->entity_data()));
52     }
53   }
54   if (entity_data != nullptr && entity_data->HasExplicitlySetFields()) {
55     suggestion->serialized_entity_data = entity_data->Serialize();
56   }
57 }
58 
SuggestTextRepliesFromCapturingMatch(const MutableFlatbufferBuilder * entity_data_builder,const RulesModel_::RuleActionSpec_::RuleCapturingGroup * group,const UnicodeText & match_text,const std::string & smart_reply_action_type,std::vector<ActionSuggestion> * actions)59 void SuggestTextRepliesFromCapturingMatch(
60     const MutableFlatbufferBuilder* entity_data_builder,
61     const RulesModel_::RuleActionSpec_::RuleCapturingGroup* group,
62     const UnicodeText& match_text, const std::string& smart_reply_action_type,
63     std::vector<ActionSuggestion>* actions) {
64   if (group->text_reply() != nullptr) {
65     ActionSuggestion suggestion;
66     suggestion.response_text = match_text.ToUTF8String();
67     suggestion.type = smart_reply_action_type;
68     std::unique_ptr<MutableFlatbuffer> entity_data =
69         entity_data_builder != nullptr ? entity_data_builder->NewRoot()
70                                        : nullptr;
71     FillSuggestionFromSpec(group->text_reply(), entity_data.get(), &suggestion);
72     actions->push_back(suggestion);
73   }
74 }
75 
NormalizeMatchText(const UniLib & unilib,const RulesModel_::RuleActionSpec_::RuleCapturingGroup * group,StringPiece match_text)76 UnicodeText NormalizeMatchText(
77     const UniLib& unilib,
78     const RulesModel_::RuleActionSpec_::RuleCapturingGroup* group,
79     StringPiece match_text) {
80   return NormalizeMatchText(unilib, group,
81                             UTF8ToUnicodeText(match_text, /*do_copy=*/false));
82 }
83 
NormalizeMatchText(const UniLib & unilib,const RulesModel_::RuleActionSpec_::RuleCapturingGroup * group,const UnicodeText match_text)84 UnicodeText NormalizeMatchText(
85     const UniLib& unilib,
86     const RulesModel_::RuleActionSpec_::RuleCapturingGroup* group,
87     const UnicodeText match_text) {
88   if (group->normalization_options() == nullptr) {
89     return match_text;
90   }
91   return NormalizeText(unilib, group->normalization_options(), match_text);
92 }
93 
FillAnnotationFromCapturingMatch(const CodepointSpan & span,const RulesModel_::RuleActionSpec_::RuleCapturingGroup * group,const int message_index,StringPiece match_text,ActionSuggestionAnnotation * annotation)94 bool FillAnnotationFromCapturingMatch(
95     const CodepointSpan& span,
96     const RulesModel_::RuleActionSpec_::RuleCapturingGroup* group,
97     const int message_index, StringPiece match_text,
98     ActionSuggestionAnnotation* annotation) {
99   if (group->annotation_name() == nullptr &&
100       group->annotation_type() == nullptr) {
101     return false;
102   }
103   annotation->span.span = span;
104   annotation->span.message_index = message_index;
105   annotation->span.text = match_text.ToString();
106   if (group->annotation_name() != nullptr) {
107     annotation->name = group->annotation_name()->str();
108   }
109   if (group->annotation_type() != nullptr) {
110     annotation->entity.collection = group->annotation_type()->str();
111   }
112   return true;
113 }
114 
MergeEntityDataFromCapturingMatch(const RulesModel_::RuleActionSpec_::RuleCapturingGroup * group,StringPiece match_text,MutableFlatbuffer * buffer)115 bool MergeEntityDataFromCapturingMatch(
116     const RulesModel_::RuleActionSpec_::RuleCapturingGroup* group,
117     StringPiece match_text, MutableFlatbuffer* buffer) {
118   if (group->entity_field() != nullptr) {
119     if (!buffer->ParseAndSet(group->entity_field(), match_text.ToString())) {
120       TC3_LOG(ERROR) << "Could not set entity data from rule capturing group.";
121       return false;
122     }
123   }
124   if (group->entity_data() != nullptr) {
125     if (!buffer->MergeFrom(reinterpret_cast<const flatbuffers::Table*>(
126             group->entity_data()))) {
127       TC3_LOG(ERROR) << "Could not set entity data for capturing match.";
128       return false;
129     }
130   }
131   return true;
132 }
133 
ConvertDatetimeToTime(std::vector<AnnotatedSpan> * annotations)134 void ConvertDatetimeToTime(std::vector<AnnotatedSpan>* annotations) {
135   for (int i = 0; i < annotations->size(); i++) {
136     ClassificationResult* classification =
137         &(*annotations)[i].classification.front();
138     // Specialize datetime annotation to time annotation if no date
139     // component is present.
140     if (classification->collection == Collections::DateTime() &&
141         classification->datetime_parse_result.IsSet()) {
142       bool has_only_time = true;
143       for (const DatetimeComponent& component :
144            classification->datetime_parse_result.datetime_components) {
145         if (component.component_type !=
146                 DatetimeComponent::ComponentType::UNSPECIFIED &&
147             component.component_type < DatetimeComponent::ComponentType::HOUR) {
148           has_only_time = false;
149           break;
150         }
151       }
152       if (has_only_time) {
153         classification->collection = kTimeAnnotation;
154       }
155     }
156   }
157 }
158 
159 }  // namespace libtextclassifier3
160