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