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