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