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 package com.android.textclassifier.common.logging; 18 19 import android.os.Bundle; 20 import androidx.annotation.IntDef; 21 import com.google.common.base.Preconditions; 22 import java.lang.annotation.Retention; 23 import java.lang.annotation.RetentionPolicy; 24 import java.util.Arrays; 25 import java.util.Locale; 26 import javax.annotation.Nonnull; 27 import javax.annotation.Nullable; 28 29 /** 30 * This class represents events that are sent by components to a TextClassifier to report something 31 * of note that relates to a feature powered by the TextClassifier. The TextClassifier may log these 32 * events or use them to improve future responses to queries. 33 * 34 * <p>Each category of events has its their own subclass. Events of each type have an associated set 35 * of related properties. You can find their specification in the subclasses. 36 */ 37 public abstract class TextClassifierEvent { 38 39 /** Category of the event */ 40 @Retention(RetentionPolicy.SOURCE) 41 @IntDef({ 42 CATEGORY_SELECTION, 43 CATEGORY_LINKIFY, 44 CATEGORY_CONVERSATION_ACTIONS, 45 CATEGORY_LANGUAGE_DETECTION 46 }) 47 public @interface Category { 48 // For custom event categories, use range 1000+. 49 } 50 51 /** 52 * Smart selection 53 * 54 * @see TextSelectionEvent 55 */ 56 public static final int CATEGORY_SELECTION = 1; 57 /** 58 * Linkify 59 * 60 * @see TextLinkifyEvent 61 */ 62 public static final int CATEGORY_LINKIFY = 2; 63 /** 64 * Conversation actions 65 * 66 * @see ConversationActionsEvent 67 */ 68 public static final int CATEGORY_CONVERSATION_ACTIONS = 3; 69 /** 70 * Language detection 71 * 72 * @see LanguageDetectionEvent 73 */ 74 public static final int CATEGORY_LANGUAGE_DETECTION = 4; 75 76 /** Type of the event */ 77 @Retention(RetentionPolicy.SOURCE) 78 @IntDef({ 79 TYPE_SELECTION_STARTED, 80 TYPE_SELECTION_MODIFIED, 81 TYPE_SMART_SELECTION_SINGLE, 82 TYPE_SMART_SELECTION_MULTI, 83 TYPE_AUTO_SELECTION, 84 TYPE_ACTIONS_SHOWN, 85 TYPE_LINK_CLICKED, 86 TYPE_OVERTYPE, 87 TYPE_COPY_ACTION, 88 TYPE_PASTE_ACTION, 89 TYPE_CUT_ACTION, 90 TYPE_SHARE_ACTION, 91 TYPE_SMART_ACTION, 92 TYPE_SELECTION_DRAG, 93 TYPE_SELECTION_DESTROYED, 94 TYPE_OTHER_ACTION, 95 TYPE_SELECT_ALL, 96 TYPE_SELECTION_RESET, 97 TYPE_MANUAL_REPLY, 98 TYPE_ACTIONS_GENERATED, 99 TYPE_LINKS_GENERATED 100 }) 101 public @interface Type { 102 // For custom event types, use range 1,000,000+. 103 } 104 105 // All these event type constants are required to match with those defined in 106 // textclassifier_enums.proto. 107 /** User started a new selection. */ 108 public static final int TYPE_SELECTION_STARTED = 1; 109 /** User modified an existing selection. */ 110 public static final int TYPE_SELECTION_MODIFIED = 2; 111 /** Smart selection triggered for a single token (word). */ 112 public static final int TYPE_SMART_SELECTION_SINGLE = 3; 113 /** Smart selection triggered spanning multiple tokens (words). */ 114 public static final int TYPE_SMART_SELECTION_MULTI = 4; 115 /** Something else other than user or the default TextClassifier triggered a selection. */ 116 public static final int TYPE_AUTO_SELECTION = 5; 117 /** Smart actions shown to the user. */ 118 public static final int TYPE_ACTIONS_SHOWN = 6; 119 /** User clicked a link. */ 120 public static final int TYPE_LINK_CLICKED = 7; 121 /** User typed over the selection. */ 122 public static final int TYPE_OVERTYPE = 8; 123 /** User clicked on Copy action. */ 124 public static final int TYPE_COPY_ACTION = 9; 125 /** User clicked on Paste action. */ 126 public static final int TYPE_PASTE_ACTION = 10; 127 /** User clicked on Cut action. */ 128 public static final int TYPE_CUT_ACTION = 11; 129 /** User clicked on Share action. */ 130 public static final int TYPE_SHARE_ACTION = 12; 131 /** User clicked on a Smart action. */ 132 public static final int TYPE_SMART_ACTION = 13; 133 /** User dragged+dropped the selection. */ 134 public static final int TYPE_SELECTION_DRAG = 14; 135 /** Selection is destroyed. */ 136 public static final int TYPE_SELECTION_DESTROYED = 15; 137 /** User clicked on a custom action. */ 138 public static final int TYPE_OTHER_ACTION = 16; 139 /** User clicked on Select All action */ 140 public static final int TYPE_SELECT_ALL = 17; 141 /** User reset the smart selection. */ 142 public static final int TYPE_SELECTION_RESET = 18; 143 /** User composed a reply. */ 144 public static final int TYPE_MANUAL_REPLY = 19; 145 /** TextClassifier generated some actions */ 146 public static final int TYPE_ACTIONS_GENERATED = 20; 147 /** Some text links were generated. */ 148 public static final int TYPE_LINKS_GENERATED = 21; 149 150 @Category private final int eventCategory; 151 @Type private final int eventType; 152 @Nullable private final String[] entityTypes; 153 @Nullable private TextClassificationContext eventContext; 154 @Nullable private final String resultId; 155 private final int eventIndex; 156 private final float[] scores; 157 @Nullable private final String modelName; 158 private final int[] actionIndices; 159 @Nullable private final Locale locale; 160 private final Bundle extras; 161 TextClassifierEvent(Builder<?> builder)162 private TextClassifierEvent(Builder<?> builder) { 163 eventCategory = builder.eventCategory; 164 eventType = builder.eventType; 165 entityTypes = builder.entityTypes; 166 eventContext = builder.eventContext; 167 resultId = builder.resultId; 168 eventIndex = builder.eventIndex; 169 scores = builder.scores; 170 modelName = builder.modelName; 171 actionIndices = builder.actionIndices; 172 locale = builder.locale; 173 extras = builder.extras == null ? Bundle.EMPTY : builder.extras; 174 } 175 176 /** Returns the event category. e.g. {@link #CATEGORY_SELECTION}. */ 177 @Category getEventCategory()178 public int getEventCategory() { 179 return eventCategory; 180 } 181 182 /** Returns the event type. e.g. {@link #TYPE_SELECTION_STARTED}. */ 183 @Type getEventType()184 public int getEventType() { 185 return eventType; 186 } 187 188 /** 189 * Returns an array of entity types. e.g. {@link TextClassifier#TYPE_ADDRESS}. 190 * 191 * @see Builder#setEntityTypes(String...) for supported types. 192 */ 193 @Nonnull getEntityTypes()194 public String[] getEntityTypes() { 195 return entityTypes; 196 } 197 198 /** Returns the event context. */ 199 @Nullable getEventContext()200 public TextClassificationContext getEventContext() { 201 return eventContext; 202 } 203 204 /** 205 * Sets the event context. 206 * 207 * <p>Package-private for SystemTextClassifier's use. 208 */ setEventContext(@ullable TextClassificationContext eventContext)209 void setEventContext(@Nullable TextClassificationContext eventContext) { 210 this.eventContext = eventContext; 211 } 212 213 /** Returns the id of the text classifier result related to this event. */ 214 @Nullable getResultId()215 public String getResultId() { 216 return resultId; 217 } 218 219 /** Returns the index of this event in the series of event it belongs to. */ getEventIndex()220 public int getEventIndex() { 221 return eventIndex; 222 } 223 224 /** Returns the scores of the suggestions. */ getScores()225 public float[] getScores() { 226 return scores; 227 } 228 229 /** Returns the model name. */ 230 @Nullable getModelName()231 public String getModelName() { 232 return modelName; 233 } 234 235 /** 236 * Returns the indices of the actions relating to this event. Actions are usually returned by the 237 * text classifier in priority order with the most preferred action at index 0. This list gives an 238 * indication of the position of the actions that are being reported. 239 * 240 * @see Builder#setActionIndices(int...) 241 */ getActionIndices()242 public int[] getActionIndices() { 243 return actionIndices; 244 } 245 246 /** Returns the detected locale. */ 247 @Nullable getLocale()248 public Locale getLocale() { 249 return locale; 250 } 251 252 /** 253 * Returns a bundle containing non-structured extra information about this event. 254 * 255 * <p><b>NOTE: </b>Do not modify this bundle. 256 */ 257 @Nonnull getExtras()258 public Bundle getExtras() { 259 return extras; 260 } 261 262 @Override toString()263 public String toString() { 264 StringBuilder out = new StringBuilder(128); 265 out.append(this.getClass().getSimpleName()); 266 out.append("{"); 267 out.append("mEventCategory=").append(eventCategory); 268 out.append(", mEventType=").append(eventType); 269 out.append(", mEntityTypes=").append(Arrays.toString(entityTypes)); 270 out.append(", mEventContext=").append(eventContext); 271 out.append(", mResultId=").append(resultId); 272 out.append(", mEventIndex=").append(eventIndex); 273 out.append(", mExtras=").append(extras); 274 out.append(", mScores=").append(Arrays.toString(scores)); 275 out.append(", mModelName=").append(modelName); 276 out.append(", mActionIndices=").append(Arrays.toString(actionIndices)); 277 toString(out); 278 out.append("}"); 279 return out.toString(); 280 } 281 282 /** 283 * Overrides this to append extra fields to the output of {@link #toString()}. 284 * 285 * <p>Extra fields should be formatted like this: ", {field_name}={field_value}". 286 */ toString(StringBuilder out)287 void toString(StringBuilder out) {} 288 289 /** 290 * Builder to build a text classifier event. 291 * 292 * @param <T> The subclass to be built. 293 */ 294 public abstract static class Builder<T extends Builder<T>> { 295 296 private final int eventCategory; 297 private final int eventType; 298 private String[] entityTypes = new String[0]; 299 @Nullable private TextClassificationContext eventContext; 300 @Nullable private String resultId; 301 private int eventIndex; 302 private float[] scores = new float[0]; 303 @Nullable private String modelName; 304 private int[] actionIndices = new int[0]; 305 @Nullable private Locale locale; 306 @Nullable private Bundle extras; 307 308 /** 309 * Creates a builder for building {@link TextClassifierEvent}s. 310 * 311 * @param eventCategory The event category. e.g. {@link #CATEGORY_SELECTION} 312 * @param eventType The event type. e.g. {@link #TYPE_SELECTION_STARTED} 313 */ Builder(@ategory int eventCategory, @Type int eventType)314 private Builder(@Category int eventCategory, @Type int eventType) { 315 this.eventCategory = eventCategory; 316 this.eventType = eventType; 317 } 318 319 /** 320 * Sets the entity types. e.g. {@link android.view.textclassifier.TextClassifier#TYPE_ADDRESS}. 321 * 322 * <p>Supported types: 323 * 324 * <p>See {@link android.view.textclassifier.TextClassifier.EntityType} 325 * 326 * <p>See {@link android.view.textclassifier.ConversationAction.ActionType} 327 * 328 * <p>See {@link Locale#toLanguageTag()} 329 */ setEntityTypes(String... entityTypes)330 public T setEntityTypes(String... entityTypes) { 331 Preconditions.checkNotNull(entityTypes); 332 this.entityTypes = new String[entityTypes.length]; 333 System.arraycopy(entityTypes, 0, this.entityTypes, 0, entityTypes.length); 334 return self(); 335 } 336 337 /** Sets the event context. */ setEventContext(@ullable TextClassificationContext eventContext)338 public T setEventContext(@Nullable TextClassificationContext eventContext) { 339 this.eventContext = eventContext; 340 return self(); 341 } 342 343 /** Sets the id of the text classifier result related to this event. */ 344 @Nonnull setResultId(@ullable String resultId)345 public T setResultId(@Nullable String resultId) { 346 this.resultId = resultId; 347 return self(); 348 } 349 350 /** Sets the index of this event in the series of events it belongs to. */ 351 @Nonnull setEventIndex(int eventIndex)352 public T setEventIndex(int eventIndex) { 353 this.eventIndex = eventIndex; 354 return self(); 355 } 356 357 /** Sets the scores of the suggestions. */ 358 @Nonnull setScores(@onnull float... scores)359 public T setScores(@Nonnull float... scores) { 360 Preconditions.checkNotNull(scores); 361 this.scores = new float[scores.length]; 362 System.arraycopy(scores, 0, this.scores, 0, scores.length); 363 return self(); 364 } 365 366 /** Sets the model name string. */ 367 @Nonnull setModelName(@ullable String modelVersion)368 public T setModelName(@Nullable String modelVersion) { 369 modelName = modelVersion; 370 return self(); 371 } 372 373 /** 374 * Sets the indices of the actions involved in this event. Actions are usually returned by the 375 * text classifier in priority order with the most preferred action at index 0. These indices 376 * give an indication of the position of the actions that are being reported. 377 * 378 * <p>E.g. 379 * 380 * <pre> 381 * // 3 smart actions are shown at index 0, 1, 2 respectively in response to a link click. 382 * new TextClassifierEvent.Builder(CATEGORY_LINKIFY, TYPE_ACTIONS_SHOWN) 383 * .setEventIndex(0, 1, 2) 384 * ... 385 * .build(); 386 * 387 * ... 388 * 389 * // Smart action at index 1 is activated. 390 * new TextClassifierEvent.Builder(CATEGORY_LINKIFY, TYPE_SMART_ACTION) 391 * .setEventIndex(1) 392 * ... 393 * .build(); 394 * </pre> 395 * 396 * @see android.view.textclassifier.TextClassification#getActions() 397 */ 398 @Nonnull setActionIndices(@onnull int... actionIndices)399 public T setActionIndices(@Nonnull int... actionIndices) { 400 this.actionIndices = new int[actionIndices.length]; 401 System.arraycopy(actionIndices, 0, this.actionIndices, 0, actionIndices.length); 402 return self(); 403 } 404 405 /** Sets the detected locale. */ 406 @Nonnull setLocale(@ullable Locale locale)407 public T setLocale(@Nullable Locale locale) { 408 this.locale = locale; 409 return self(); 410 } 411 412 /** 413 * Sets a bundle containing non-structured extra information about the event. 414 * 415 * <p><b>NOTE: </b>Prefer to set only immutable values on the bundle otherwise, avoid updating 416 * the internals of this bundle as it may have unexpected consequences on the clients of the 417 * built event object. For similar reasons, avoid depending on mutable objects in this bundle. 418 */ 419 @Nonnull setExtras(@onnull Bundle extras)420 public T setExtras(@Nonnull Bundle extras) { 421 this.extras = Preconditions.checkNotNull(extras); 422 return self(); 423 } 424 self()425 abstract T self(); 426 } 427 428 /** 429 * This class represents events that are related to the smart text selection feature. 430 * 431 * <p> 432 * 433 * <pre> 434 * // User started a selection. e.g. "York" in text "New York City, NY". 435 * new TextSelectionEvent.Builder(TYPE_SELECTION_STARTED) 436 * .setEventContext(classificationContext) 437 * .setEventIndex(0) 438 * .build(); 439 * 440 * // System smart-selects a recognized entity. e.g. "New York City". 441 * new TextSelectionEvent.Builder(TYPE_SMART_SELECTION_MULTI) 442 * .setEventContext(classificationContext) 443 * .setResultId(textSelection.getId()) 444 * .setRelativeWordStartIndex(-1) // Goes back one word to "New" from "York". 445 * .setRelativeWordEndIndex(2) // Goes forward 2 words from "York" to start of ",". 446 * .setEntityTypes(textClassification.getEntity(0)) 447 * .setScore(textClassification.getConfidenceScore(entityType)) 448 * .setEventIndex(1) 449 * .build(); 450 * 451 * // User resets the selection to the original selection. i.e. "York". 452 * new TextSelectionEvent.Builder(TYPE_SELECTION_RESET) 453 * .setEventContext(classificationContext) 454 * .setResultId(textSelection.getId()) 455 * .setRelativeSuggestedWordStartIndex(-1) // Repeated from above. 456 * .setRelativeSuggestedWordEndIndex(2) // Repeated from above. 457 * .setRelativeWordStartIndex(0) // Original selection is always at (0, 1]. 458 * .setRelativeWordEndIndex(1) 459 * .setEntityTypes(textClassification.getEntity(0)) 460 * .setScore(textClassification.getConfidenceScore(entityType)) 461 * .setEventIndex(2) 462 * .build(); 463 * 464 * // User modified the selection. e.g. "New". 465 * new TextSelectionEvent.Builder(TYPE_SELECTION_MODIFIED) 466 * .setEventContext(classificationContext) 467 * .setResultId(textSelection.getId()) 468 * .setRelativeSuggestedWordStartIndex(-1) // Repeated from above. 469 * .setRelativeSuggestedWordEndIndex(2) // Repeated from above. 470 * .setRelativeWordStartIndex(-1) // Goes backward one word from "York" to 471 * "New". 472 * .setRelativeWordEndIndex(0) // Goes backward one word to exclude "York". 473 * .setEntityTypes(textClassification.getEntity(0)) 474 * .setScore(textClassification.getConfidenceScore(entityType)) 475 * .setEventIndex(3) 476 * .build(); 477 * 478 * // Smart (contextual) actions (at indices, 0, 1, 2) presented to the user. 479 * // e.g. "Map", "Ride share", "Explore". 480 * new TextSelectionEvent.Builder(TYPE_ACTIONS_SHOWN) 481 * .setEventContext(classificationContext) 482 * .setResultId(textClassification.getId()) 483 * .setEntityTypes(textClassification.getEntity(0)) 484 * .setScore(textClassification.getConfidenceScore(entityType)) 485 * .setActionIndices(0, 1, 2) 486 * .setEventIndex(4) 487 * .build(); 488 * 489 * // User chooses the "Copy" action. 490 * new TextSelectionEvent.Builder(TYPE_COPY_ACTION) 491 * .setEventContext(classificationContext) 492 * .setResultId(textClassification.getId()) 493 * .setEntityTypes(textClassification.getEntity(0)) 494 * .setScore(textClassification.getConfidenceScore(entityType)) 495 * .setEventIndex(5) 496 * .build(); 497 * 498 * // User chooses smart action at index 1. i.e. "Ride share". 499 * new TextSelectionEvent.Builder(TYPE_SMART_ACTION) 500 * .setEventContext(classificationContext) 501 * .setResultId(textClassification.getId()) 502 * .setEntityTypes(textClassification.getEntity(0)) 503 * .setScore(textClassification.getConfidenceScore(entityType)) 504 * .setActionIndices(1) 505 * .setEventIndex(5) 506 * .build(); 507 * 508 * // Selection dismissed. 509 * new TextSelectionEvent.Builder(TYPE_SELECTION_DESTROYED) 510 * .setEventContext(classificationContext) 511 * .setResultId(textClassification.getId()) 512 * .setEntityTypes(textClassification.getEntity(0)) 513 * .setScore(textClassification.getConfidenceScore(entityType)) 514 * .setEventIndex(6) 515 * .build(); 516 * </pre> 517 * 518 * <p> 519 */ 520 public static final class TextSelectionEvent extends TextClassifierEvent { 521 522 final int relativeWordStartIndex; 523 final int relativeWordEndIndex; 524 final int relativeSuggestedWordStartIndex; 525 final int relativeSuggestedWordEndIndex; 526 TextSelectionEvent(TextSelectionEvent.Builder builder)527 private TextSelectionEvent(TextSelectionEvent.Builder builder) { 528 super(builder); 529 relativeWordStartIndex = builder.relativeWordStartIndex; 530 relativeWordEndIndex = builder.relativeWordEndIndex; 531 relativeSuggestedWordStartIndex = builder.relativeSuggestedWordStartIndex; 532 relativeSuggestedWordEndIndex = builder.relativeSuggestedWordEndIndex; 533 } 534 535 /** Returns the relative word index of the start of the selection. */ getRelativeWordStartIndex()536 public int getRelativeWordStartIndex() { 537 return relativeWordStartIndex; 538 } 539 540 /** Returns the relative word (exclusive) index of the end of the selection. */ getRelativeWordEndIndex()541 public int getRelativeWordEndIndex() { 542 return relativeWordEndIndex; 543 } 544 545 /** Returns the relative word index of the start of the smart selection. */ getRelativeSuggestedWordStartIndex()546 public int getRelativeSuggestedWordStartIndex() { 547 return relativeSuggestedWordStartIndex; 548 } 549 550 /** Returns the relative word (exclusive) index of the end of the smart selection. */ getRelativeSuggestedWordEndIndex()551 public int getRelativeSuggestedWordEndIndex() { 552 return relativeSuggestedWordEndIndex; 553 } 554 555 @Override toString(StringBuilder out)556 void toString(StringBuilder out) { 557 out.append(", getRelativeWordStartIndex=").append(relativeWordStartIndex); 558 out.append(", getRelativeWordEndIndex=").append(relativeWordEndIndex); 559 out.append(", getRelativeSuggestedWordStartIndex=").append(relativeSuggestedWordStartIndex); 560 out.append(", getRelativeSuggestedWordEndIndex=").append(relativeSuggestedWordEndIndex); 561 } 562 563 /** Builder class for {@link TextSelectionEvent}. */ 564 public static final class Builder 565 extends TextClassifierEvent.Builder<TextSelectionEvent.Builder> { 566 int relativeWordStartIndex; 567 int relativeWordEndIndex; 568 int relativeSuggestedWordStartIndex; 569 int relativeSuggestedWordEndIndex; 570 571 /** 572 * Creates a builder for building {@link TextSelectionEvent}s. 573 * 574 * @param eventType The event type. e.g. {@link #TYPE_SELECTION_STARTED} 575 */ Builder(@ype int eventType)576 public Builder(@Type int eventType) { 577 super(CATEGORY_SELECTION, eventType); 578 } 579 580 /** Sets the relative word index of the start of the selection. */ 581 @Nonnull setRelativeWordStartIndex(int relativeWordStartIndex)582 public Builder setRelativeWordStartIndex(int relativeWordStartIndex) { 583 this.relativeWordStartIndex = relativeWordStartIndex; 584 return this; 585 } 586 587 /** Sets the relative word (exclusive) index of the end of the selection. */ 588 @Nonnull setRelativeWordEndIndex(int relativeWordEndIndex)589 public Builder setRelativeWordEndIndex(int relativeWordEndIndex) { 590 this.relativeWordEndIndex = relativeWordEndIndex; 591 return this; 592 } 593 594 /** Sets the relative word index of the start of the smart selection. */ 595 @Nonnull setRelativeSuggestedWordStartIndex(int relativeSuggestedWordStartIndex)596 public Builder setRelativeSuggestedWordStartIndex(int relativeSuggestedWordStartIndex) { 597 this.relativeSuggestedWordStartIndex = relativeSuggestedWordStartIndex; 598 return this; 599 } 600 601 /** Sets the relative word (exclusive) index of the end of the smart selection. */ 602 @Nonnull setRelativeSuggestedWordEndIndex(int relativeSuggestedWordEndIndex)603 public Builder setRelativeSuggestedWordEndIndex(int relativeSuggestedWordEndIndex) { 604 this.relativeSuggestedWordEndIndex = relativeSuggestedWordEndIndex; 605 return this; 606 } 607 608 @Override self()609 TextSelectionEvent.Builder self() { 610 return this; 611 } 612 613 /** Builds and returns a {@link TextSelectionEvent}. */ 614 @Nonnull build()615 public TextSelectionEvent build() { 616 return new TextSelectionEvent(this); 617 } 618 } 619 } 620 621 /** 622 * This class represents events that are related to the smart linkify feature. 623 * 624 * <p> 625 * 626 * <pre> 627 * // User clicked on a link. 628 * new TextLinkifyEvent.Builder(TYPE_LINK_CLICKED) 629 * .setEventContext(classificationContext) 630 * .setResultId(textClassification.getId()) 631 * .setEntityTypes(textClassification.getEntity(0)) 632 * .setScore(textClassification.getConfidenceScore(entityType)) 633 * .setEventIndex(0) 634 * .build(); 635 * 636 * // Smart (contextual) actions presented to the user in response to a link click. 637 * new TextLinkifyEvent.Builder(TYPE_ACTIONS_SHOWN) 638 * .setEventContext(classificationContext) 639 * .setResultId(textClassification.getId()) 640 * .setEntityTypes(textClassification.getEntity(0)) 641 * .setScore(textClassification.getConfidenceScore(entityType)) 642 * .setActionIndices(range(textClassification.getActions().size())) 643 * .setEventIndex(1) 644 * .build(); 645 * 646 * // User chooses smart action at index 0. 647 * new TextLinkifyEvent.Builder(TYPE_SMART_ACTION) 648 * .setEventContext(classificationContext) 649 * .setResultId(textClassification.getId()) 650 * .setEntityTypes(textClassification.getEntity(0)) 651 * .setScore(textClassification.getConfidenceScore(entityType)) 652 * .setActionIndices(0) 653 * .setEventIndex(2) 654 * .build(); 655 * </pre> 656 */ 657 public static final class TextLinkifyEvent extends TextClassifierEvent { 658 TextLinkifyEvent(TextLinkifyEvent.Builder builder)659 private TextLinkifyEvent(TextLinkifyEvent.Builder builder) { 660 super(builder); 661 } 662 663 /** Builder class for {@link TextLinkifyEvent}. */ 664 public static final class Builder 665 extends TextClassifierEvent.Builder<TextLinkifyEvent.Builder> { 666 /** 667 * Creates a builder for building {@link TextLinkifyEvent}s. 668 * 669 * @param eventType The event type. e.g. {@link #TYPE_SMART_ACTION} 670 */ Builder(@ype int eventType)671 public Builder(@Type int eventType) { 672 super(TextClassifierEvent.CATEGORY_LINKIFY, eventType); 673 } 674 675 @Override self()676 Builder self() { 677 return this; 678 } 679 680 /** Builds and returns a {@link TextLinkifyEvent}. */ 681 @Nonnull build()682 public TextLinkifyEvent build() { 683 return new TextLinkifyEvent(this); 684 } 685 } 686 } 687 688 /** 689 * This class represents events that are related to the language detection feature. 690 * <p> 691 * <pre> 692 * // Translate action shown for foreign text. 693 * new LanguageDetectionEvent.Builder(TYPE_ACTIONS_SHOWN) 694 * .setEventContext(classificationContext) 695 * .setResultId(textClassification.getId()) 696 * .setEntityTypes(language) 697 * .setScore(score) 698 * .setActionIndices(textClassification.getActions().indexOf(translateAction)) 699 * .setEventIndex(0) 700 * .build(); 701 * 702 * // Translate action selected. 703 * new LanguageDetectionEvent.Builder(TYPE_SMART_ACTION) 704 * .setEventContext(classificationContext) 705 * .setResultId(textClassification.getId()) 706 * .setEntityTypes(language) 707 * .setScore(score) 708 * .setActionIndices(textClassification.getActions().indexOf(translateAction)) 709 * .setEventIndex(1) 710 * .build(); 711 */ 712 public static final class LanguageDetectionEvent extends TextClassifierEvent { 713 LanguageDetectionEvent(LanguageDetectionEvent.Builder builder)714 private LanguageDetectionEvent(LanguageDetectionEvent.Builder builder) { 715 super(builder); 716 } 717 718 /** Builder class for {@link LanguageDetectionEvent}. */ 719 public static final class Builder 720 extends TextClassifierEvent.Builder<LanguageDetectionEvent.Builder> { 721 722 /** 723 * Creates a builder for building {@link TextSelectionEvent}s. 724 * 725 * @param eventType The event type. e.g. {@link #TYPE_SMART_ACTION} 726 */ Builder(@ype int eventType)727 public Builder(@Type int eventType) { 728 super(TextClassifierEvent.CATEGORY_LANGUAGE_DETECTION, eventType); 729 } 730 731 @Override self()732 Builder self() { 733 return this; 734 } 735 736 /** Builds and returns a {@link LanguageDetectionEvent}. */ 737 @Nonnull build()738 public LanguageDetectionEvent build() { 739 return new LanguageDetectionEvent(this); 740 } 741 } 742 } 743 744 /** 745 * This class represents events that are related to the conversation actions feature. 746 * 747 * <p> 748 * 749 * <pre> 750 * // Conversation (contextual) actions/replies generated. 751 * new ConversationActionsEvent.Builder(TYPE_ACTIONS_GENERATED) 752 * .setEventContext(classificationContext) 753 * .setResultId(conversationActions.getId()) 754 * .setEntityTypes(getTypes(conversationActions)) 755 * .setActionIndices(range(conversationActions.getActions().size())) 756 * .setEventIndex(0) 757 * .build(); 758 * 759 * // Conversation actions/replies presented to user. 760 * new ConversationActionsEvent.Builder(TYPE_ACTIONS_SHOWN) 761 * .setEventContext(classificationContext) 762 * .setResultId(conversationActions.getId()) 763 * .setEntityTypes(getTypes(conversationActions)) 764 * .setActionIndices(range(conversationActions.getActions().size())) 765 * .setEventIndex(1) 766 * .build(); 767 * 768 * // User clicked the "Reply" button to compose their custom reply. 769 * new ConversationActionsEvent.Builder(TYPE_MANUAL_REPLY) 770 * .setEventContext(classificationContext) 771 * .setResultId(conversationActions.getId()) 772 * .setEventIndex(2) 773 * .build(); 774 * 775 * // User selected a smart (contextual) action/reply. 776 * new ConversationActionsEvent.Builder(TYPE_SMART_ACTION) 777 * .setEventContext(classificationContext) 778 * .setResultId(conversationActions.getId()) 779 * .setEntityTypes(conversationActions.get(1).getType()) 780 * .setScore(conversationAction.get(1).getConfidenceScore()) 781 * .setActionIndices(1) 782 * .setEventIndex(2) 783 * .build(); 784 * </pre> 785 */ 786 public static final class ConversationActionsEvent extends TextClassifierEvent { 787 ConversationActionsEvent(ConversationActionsEvent.Builder builder)788 private ConversationActionsEvent(ConversationActionsEvent.Builder builder) { 789 super(builder); 790 } 791 792 /** Builder class for {@link ConversationActionsEvent}. */ 793 public static final class Builder 794 extends TextClassifierEvent.Builder<ConversationActionsEvent.Builder> { 795 /** 796 * Creates a builder for building {@link TextSelectionEvent}s. 797 * 798 * @param eventType The event type. e.g. {@link #TYPE_SMART_ACTION} 799 */ Builder(@ype int eventType)800 public Builder(@Type int eventType) { 801 super(TextClassifierEvent.CATEGORY_CONVERSATION_ACTIONS, eventType); 802 } 803 804 @Override self()805 Builder self() { 806 return this; 807 } 808 809 /** Builds and returns a {@link ConversationActionsEvent}. */ 810 @Nonnull build()811 public ConversationActionsEvent build() { 812 return new ConversationActionsEvent(this); 813 } 814 } 815 } 816 } 817