| /* |
| * Copyright 2017 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package android.view.textclassifier; |
| |
| import android.annotation.FloatRange; |
| import android.annotation.NonNull; |
| import android.annotation.Nullable; |
| import android.os.LocaleList; |
| import android.text.SpannableString; |
| import android.text.style.ClickableSpan; |
| |
| import com.android.internal.util.Preconditions; |
| |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.function.Function; |
| |
| /** |
| * A collection of links, representing subsequences of text and the entity types (phone number, |
| * address, url, etc) they may be. |
| */ |
| public final class TextLinks { |
| private final String mFullText; |
| private final List<TextLink> mLinks; |
| |
| private TextLinks(String fullText, Collection<TextLink> links) { |
| mFullText = fullText; |
| mLinks = Collections.unmodifiableList(new ArrayList<>(links)); |
| } |
| |
| /** |
| * Returns an unmodifiable Collection of the links. |
| */ |
| public Collection<TextLink> getLinks() { |
| return mLinks; |
| } |
| |
| /** |
| * Annotates the given text with the generated links. It will fail if the provided text doesn't |
| * match the original text used to crete the TextLinks. |
| * |
| * @param text the text to apply the links to. Must match the original text. |
| * @param spanFactory a factory to generate spans from TextLinks. Will use a default if null. |
| * |
| * @return Success or failure. |
| */ |
| public boolean apply( |
| @NonNull SpannableString text, |
| @Nullable Function<TextLink, ClickableSpan> spanFactory) { |
| Preconditions.checkNotNull(text); |
| if (!mFullText.equals(text.toString())) { |
| return false; |
| } |
| |
| if (spanFactory == null) { |
| spanFactory = DEFAULT_SPAN_FACTORY; |
| } |
| for (TextLink link : mLinks) { |
| final ClickableSpan span = spanFactory.apply(link); |
| if (span != null) { |
| text.setSpan(span, link.getStart(), link.getEnd(), 0); |
| } |
| } |
| return true; |
| } |
| |
| /** |
| * A link, identifying a substring of text and possible entity types for it. |
| */ |
| public static final class TextLink { |
| private final EntityConfidence<String> mEntityScores; |
| private final String mOriginalText; |
| private final int mStart; |
| private final int mEnd; |
| |
| /** |
| * Create a new TextLink. |
| * |
| * @throws IllegalArgumentException if entityScores is null or empty. |
| */ |
| public TextLink(String originalText, int start, int end, Map<String, Float> entityScores) { |
| Preconditions.checkNotNull(originalText); |
| Preconditions.checkNotNull(entityScores); |
| Preconditions.checkArgument(!entityScores.isEmpty()); |
| Preconditions.checkArgument(start <= end); |
| mOriginalText = originalText; |
| mStart = start; |
| mEnd = end; |
| mEntityScores = new EntityConfidence<>(); |
| |
| for (Map.Entry<String, Float> entry : entityScores.entrySet()) { |
| mEntityScores.setEntityType(entry.getKey(), entry.getValue()); |
| } |
| } |
| |
| /** |
| * Returns the start index of this link in the original text. |
| * |
| * @return the start index. |
| */ |
| public int getStart() { |
| return mStart; |
| } |
| |
| /** |
| * Returns the end index of this link in the original text. |
| * |
| * @return the end index. |
| */ |
| public int getEnd() { |
| return mEnd; |
| } |
| |
| /** |
| * Returns the number of entity types that have confidence scores. |
| * |
| * @return the entity count. |
| */ |
| public int getEntityCount() { |
| return mEntityScores.getEntities().size(); |
| } |
| |
| /** |
| * Returns the entity type at a given index. Entity types are sorted by confidence. |
| * |
| * @return the entity type at the provided index. |
| */ |
| @NonNull public @TextClassifier.EntityType String getEntity(int index) { |
| return mEntityScores.getEntities().get(index); |
| } |
| |
| /** |
| * Returns the confidence score for a particular entity type. |
| * |
| * @param entityType the entity type. |
| */ |
| public @FloatRange(from = 0.0, to = 1.0) float getConfidenceScore( |
| @TextClassifier.EntityType String entityType) { |
| return mEntityScores.getConfidenceScore(entityType); |
| } |
| } |
| |
| /** |
| * Optional input parameters for generating TextLinks. |
| */ |
| public static final class Options { |
| private final LocaleList mLocaleList; |
| |
| private Options(LocaleList localeList) { |
| this.mLocaleList = localeList; |
| } |
| |
| /** |
| * Builder to construct Options. |
| */ |
| public static final class Builder { |
| private LocaleList mLocaleList; |
| |
| /** |
| * Sets the LocaleList to use. |
| * |
| * @return this Builder. |
| */ |
| public Builder setLocaleList(@Nullable LocaleList localeList) { |
| this.mLocaleList = localeList; |
| return this; |
| } |
| |
| /** |
| * Builds the Options object. |
| */ |
| public Options build() { |
| return new Options(mLocaleList); |
| } |
| } |
| public @Nullable LocaleList getDefaultLocales() { |
| return mLocaleList; |
| } |
| }; |
| |
| /** |
| * A function to create spans from TextLinks. |
| * |
| * Applies only to TextViews. |
| * We can hide this until we are convinced we want it to be part of the public API. |
| * |
| * @hide |
| */ |
| public static final Function<TextLink, ClickableSpan> DEFAULT_SPAN_FACTORY = |
| new Function<TextLink, ClickableSpan>() { |
| @Override |
| public ClickableSpan apply(TextLink textLink) { |
| // TODO: Implement. |
| throw new UnsupportedOperationException("Not yet implemented"); |
| } |
| }; |
| |
| /** |
| * A builder to construct a TextLinks instance. |
| */ |
| public static final class Builder { |
| private final String mFullText; |
| private final Collection<TextLink> mLinks; |
| |
| /** |
| * Create a new TextLinks.Builder. |
| * |
| * @param fullText The full text that links will be added to. |
| */ |
| public Builder(@NonNull String fullText) { |
| mFullText = Preconditions.checkNotNull(fullText); |
| mLinks = new ArrayList<>(); |
| } |
| |
| /** |
| * Adds a TextLink. |
| * |
| * @return this instance. |
| */ |
| public Builder addLink(TextLink link) { |
| Preconditions.checkNotNull(link); |
| mLinks.add(link); |
| return this; |
| } |
| |
| /** |
| * Constructs a TextLinks instance. |
| * |
| * @return the constructed TextLinks. |
| */ |
| public TextLinks build() { |
| return new TextLinks(mFullText, mLinks); |
| } |
| } |
| } |