1c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus/* 2c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * Copyright (C) 2018 The Android Open Source Project 3c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * 4c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * Licensed under the Apache License, Version 2.0 (the "License"); 5c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * you may not use this file except in compliance with the License. 6c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * You may obtain a copy of the License at 7c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * 8c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * http://www.apache.org/licenses/LICENSE-2.0 9c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * 10c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * Unless required by applicable law or agreed to in writing, software 11c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * distributed under the License is distributed on an "AS IS" BASIS, 12c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * See the License for the specific language governing permissions and 14c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * limitations under the License. 15c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus */ 16c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 17ddf3bdd8f2a3afe5d8fd041f542ad4005a2ac869Aurimas Liutikaspackage androidx.textclassifier; 18c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 19c08637c95be5e31268baf9b434a2d710423181f5Jan Althausimport android.os.Parcel; 20c08637c95be5e31268baf9b434a2d710423181f5Jan Althausimport android.os.Parcelable; 21c65e03f6e729f8c5e5a766a1076ee3531dbdc0b2Aurimas Liutikas 22ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport androidx.annotation.IntDef; 23ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport androidx.annotation.RestrictTo; 24ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport androidx.annotation.StringDef; 25ac5fe7c617c66850fff75a9fce9979c6e5674b0fAurimas Liutikasimport androidx.collection.ArraySet; 26c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 27c08637c95be5e31268baf9b434a2d710423181f5Jan Althausimport java.lang.annotation.Retention; 28c08637c95be5e31268baf9b434a2d710423181f5Jan Althausimport java.lang.annotation.RetentionPolicy; 29c08637c95be5e31268baf9b434a2d710423181f5Jan Althausimport java.util.ArrayList; 30c08637c95be5e31268baf9b434a2d710423181f5Jan Althausimport java.util.Arrays; 31c08637c95be5e31268baf9b434a2d710423181f5Jan Althausimport java.util.Collection; 32c08637c95be5e31268baf9b434a2d710423181f5Jan Althausimport java.util.Collections; 33c08637c95be5e31268baf9b434a2d710423181f5Jan Althausimport java.util.List; 34c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 35c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus/** 36c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * Interface for providing text classification related features. 37c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * 38c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * TextClassifier acts as a proxy to either the system provided TextClassifier, or an equivalent 39c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * implementation provided by an app. Each instance of the class therefore represents one connection 40c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * to the classifier implementation. 41c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * 42c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * <p>Unless otherwise stated, methods of this interface are blocking operations. 43c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * Avoid calling them on the UI thread. 44c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus */ 45c08637c95be5e31268baf9b434a2d710423181f5Jan Althauspublic class TextClassifier { 46c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 47c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus // TODO: describe in the class documentation how a TC implementation in chosen/located. 48c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 49c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus /** Signifies that the TextClassifier did not identify an entity. */ 50c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus public static final String TYPE_UNKNOWN = ""; 51c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus /** Signifies that the classifier ran, but didn't recognize a know entity. */ 52c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus public static final String TYPE_OTHER = "other"; 53c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus /** Identifies an e-mail address. */ 54c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus public static final String TYPE_EMAIL = "email"; 55c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus /** Identifies a phone number. */ 56c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus public static final String TYPE_PHONE = "phone"; 57c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus /** Identifies a physical address. */ 58c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus public static final String TYPE_ADDRESS = "address"; 59c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus /** Identifies a URL. */ 60c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus public static final String TYPE_URL = "url"; 61c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 62c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus /** @hide */ 63c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) 64c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus @Retention(RetentionPolicy.SOURCE) 65c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus @StringDef(value = { 66c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus TYPE_UNKNOWN, 67c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus TYPE_OTHER, 68c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus TYPE_EMAIL, 69c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus TYPE_PHONE, 70c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus TYPE_ADDRESS, 71c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus TYPE_URL, 72c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus }) 73c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus @interface EntityType {} 74c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 75c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus /** Designates that the TextClassifier should identify all entity types it can. **/ 76c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus static final int ENTITY_PRESET_ALL = 0; 77c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus /** Designates that the TextClassifier should identify no entities. **/ 78c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus static final int ENTITY_PRESET_NONE = 1; 79c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus /** Designates that the TextClassifier should identify a base set of entities determined by the 80c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * TextClassifier. **/ 81c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus static final int ENTITY_PRESET_BASE = 2; 82c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 83c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus /** @hide */ 84c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) 85c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus @Retention(RetentionPolicy.SOURCE) 86c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus @IntDef(value = {ENTITY_PRESET_ALL, ENTITY_PRESET_NONE, ENTITY_PRESET_BASE}) 87c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus @interface EntityPreset {} 88c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 89c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus // TODO: add constructor, suggestSelection, classifyText, generateLinks, logEvent 90c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 91c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus /** 92c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * Returns a {@link Collection} of the entity types in the specified preset. 93c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * 94c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * @see #ENTITY_PRESET_ALL 95c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * @see #ENTITY_PRESET_NONE 96c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus */ 97c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus /* package */ Collection<String> getEntitiesForPreset(@EntityPreset int entityPreset) { 98c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus // TODO: forward call to the classifier implementation. 99c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus return Collections.EMPTY_LIST; 100c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus } 101c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 102c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus /** 103c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * Configuration object for specifying what entities to identify. 104c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * 105c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * Configs are initially based on a predefined preset, and can be modified from there. 106c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus */ 107c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus static final class EntityConfig implements Parcelable { 108c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus private final @EntityPreset int mEntityPreset; 109c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus private final Collection<String> mExcludedEntityTypes; 110c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus private final Collection<String> mIncludedEntityTypes; 111c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 112c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus EntityConfig(@EntityPreset int mEntityPreset) { 113c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus this.mEntityPreset = mEntityPreset; 114c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus mExcludedEntityTypes = new ArraySet<>(); 115c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus mIncludedEntityTypes = new ArraySet<>(); 116c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus } 117c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 118c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus /** 119c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * Specifies an entity to include in addition to any specified by the enity preset. 120c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * 121c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * Note that if an entity has been excluded, the exclusion will take precedence. 122c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus */ 123c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus public EntityConfig includeEntities(String... entities) { 124c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus mIncludedEntityTypes.addAll(Arrays.asList(entities)); 125c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus return this; 126c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus } 127c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 128c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus /** 129c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * Specifies an entity to be excluded. 130c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus */ 131c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus public EntityConfig excludeEntities(String... entities) { 132c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus mExcludedEntityTypes.addAll(Arrays.asList(entities)); 133c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus return this; 134c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus } 135c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 136c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus /** 137c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus * Returns an unmodifiable list of the final set of entities to find. 138c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus */ 139c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus public List<String> getEntities(TextClassifier textClassifier) { 140c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus ArrayList<String> entities = new ArrayList<>(); 141c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus for (String entity : textClassifier.getEntitiesForPreset(mEntityPreset)) { 142c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus if (!mExcludedEntityTypes.contains(entity)) { 143c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus entities.add(entity); 144c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus } 145c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus } 146c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus for (String entity : mIncludedEntityTypes) { 147c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus if (!mExcludedEntityTypes.contains(entity) && !entities.contains(entity)) { 148c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus entities.add(entity); 149c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus } 150c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus } 151c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus return Collections.unmodifiableList(entities); 152c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus } 153c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 154c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus @Override 155c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus public int describeContents() { 156c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus return 0; 157c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus } 158c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 159c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus @Override 160c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus public void writeToParcel(Parcel dest, int flags) { 161c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus dest.writeInt(mEntityPreset); 162c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus dest.writeStringList(new ArrayList<>(mExcludedEntityTypes)); 163c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus dest.writeStringList(new ArrayList<>(mIncludedEntityTypes)); 164c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus } 165c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 166c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus public static final Parcelable.Creator<EntityConfig> CREATOR = 167c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus new Parcelable.Creator<EntityConfig>() { 168c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus @Override 169c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus public EntityConfig createFromParcel(Parcel in) { 170c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus return new EntityConfig(in); 171c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus } 172c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 173c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus @Override 174c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus public EntityConfig[] newArray(int size) { 175c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus return new EntityConfig[size]; 176c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus } 177c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus }; 178c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus 179c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus private EntityConfig(Parcel in) { 180c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus mEntityPreset = in.readInt(); 181c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus mExcludedEntityTypes = new ArraySet<>(in.createStringArrayList()); 182c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus mIncludedEntityTypes = new ArraySet<>(in.createStringArrayList()); 183c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus } 184c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus } 185c08637c95be5e31268baf9b434a2d710423181f5Jan Althaus} 186