| package org.wordpress.android.models; |
| |
| import android.text.TextUtils; |
| |
| import org.wordpress.android.ui.reader.utils.ReaderUtils; |
| import org.wordpress.android.util.StringUtils; |
| |
| import java.io.Serializable; |
| import java.util.regex.Pattern; |
| |
| public class ReaderTag implements Serializable, FilterCriteria { |
| private String tagSlug; // tag for API calls |
| private String tagDisplayName; // tag for display, usually the same as the slug |
| private String tagTitle; // title, used for default tags |
| private String endpoint; // endpoint for updating posts with this tag |
| public final ReaderTagType tagType; |
| |
| // these are the default tags, which aren't localized in the /read/menu/ response |
| private static final String TAG_TITLE_LIKED = "Posts I Like"; |
| private static final String TAG_TITLE_DISCOVER = "Discover"; |
| public static final String TAG_TITLE_DEFAULT = TAG_TITLE_DISCOVER; |
| public static final String TAG_TITLE_FOLLOWED_SITES = "Followed Sites"; |
| |
| public ReaderTag(String slug, |
| String displayName, |
| String title, |
| String endpoint, |
| ReaderTagType tagType) { |
| // we need a slug since it's used to uniquely ID the tag (including setting it as the |
| // primary key in the tag table) |
| if (TextUtils.isEmpty(slug)) { |
| if (!TextUtils.isEmpty(title)) { |
| setTagSlug(ReaderUtils.sanitizeWithDashes(title)); |
| } else { |
| setTagSlug(getTagSlugFromEndpoint(endpoint)); |
| } |
| } else { |
| setTagSlug(slug); |
| } |
| |
| setTagDisplayName(displayName); |
| setTagTitle(title); |
| setEndpoint(endpoint); |
| this.tagType = tagType; |
| } |
| |
| public String getEndpoint() { |
| return StringUtils.notNullStr(endpoint); |
| } |
| private void setEndpoint(String endpoint) { |
| this.endpoint = StringUtils.notNullStr(endpoint); |
| } |
| |
| public String getTagTitle() { |
| return StringUtils.notNullStr(tagTitle); |
| } |
| private void setTagTitle(String title) { |
| this.tagTitle = StringUtils.notNullStr(title); |
| } |
| private boolean hasTagTitle() { |
| return !TextUtils.isEmpty(tagTitle); |
| } |
| |
| public String getTagDisplayName() { |
| return StringUtils.notNullStr(tagDisplayName); |
| } |
| private void setTagDisplayName(String displayName) { |
| this.tagDisplayName = StringUtils.notNullStr(displayName); |
| } |
| |
| public String getTagSlug() { |
| return StringUtils.notNullStr(tagSlug); |
| } |
| private void setTagSlug(String slug) { |
| this.tagSlug = StringUtils.notNullStr(slug); |
| } |
| |
| /* |
| * returns the tag name for use in the application log - if this is a default tag it returns |
| * the full tag name, otherwise it abbreviates the tag name since exposing followed tags |
| * in the log could be considered a privacy issue |
| */ |
| public String getTagNameForLog() { |
| String tagSlug = getTagSlug(); |
| if (tagType == ReaderTagType.DEFAULT) { |
| return tagSlug; |
| } else if (tagSlug.length() >= 6) { |
| return tagSlug.substring(0, 3) + "..."; |
| } else if (tagSlug.length() >= 4) { |
| return tagSlug.substring(0, 2) + "..."; |
| } else if (tagSlug.length() >= 2) { |
| return tagSlug.substring(0, 1) + "..."; |
| } else { |
| return "..."; |
| } |
| } |
| |
| /* |
| * used to ensure a tag name is valid before adding it |
| */ |
| private static final Pattern INVALID_CHARS = Pattern.compile("^.*[~#@*+%{}<>\\[\\]|\"\\_].*$"); |
| public static boolean isValidTagName(String tagName) { |
| return !TextUtils.isEmpty(tagName) |
| && !INVALID_CHARS.matcher(tagName).matches(); |
| } |
| |
| /* |
| * extracts the tag slug from a valid read/tags/[tagSlug]/posts endpoint |
| */ |
| private static String getTagSlugFromEndpoint(final String endpoint) { |
| if (TextUtils.isEmpty(endpoint)) |
| return ""; |
| |
| // make sure passed endpoint is valid |
| if (!endpoint.endsWith("/posts")) |
| return ""; |
| int start = endpoint.indexOf("/read/tags/"); |
| if (start == -1) |
| return ""; |
| |
| // skip "/read/tags/" then find the next "/" |
| start += 11; |
| int end = endpoint.indexOf("/", start); |
| if (end == -1) |
| return ""; |
| |
| return endpoint.substring(start, end); |
| } |
| |
| /* |
| * is the passed string one of the default tags? |
| */ |
| public static boolean isDefaultTagTitle(String title) { |
| if (TextUtils.isEmpty(title)) { |
| return false; |
| } |
| return (title.equalsIgnoreCase(TAG_TITLE_FOLLOWED_SITES) |
| || title.equalsIgnoreCase(TAG_TITLE_DISCOVER) |
| || title.equalsIgnoreCase(TAG_TITLE_LIKED)); |
| } |
| |
| public static boolean isSameTag(ReaderTag tag1, ReaderTag tag2) { |
| if (tag1 == null || tag2 == null) { |
| return false; |
| } |
| return tag1.tagType == tag2.tagType |
| && tag1.getTagSlug().equalsIgnoreCase(tag2.getTagSlug()); |
| } |
| |
| public boolean isPostsILike() { |
| return tagType == ReaderTagType.DEFAULT && getEndpoint().endsWith("/read/liked"); |
| } |
| |
| public boolean isFollowedSites() { |
| return tagType == ReaderTagType.DEFAULT && getEndpoint().endsWith("/read/following"); |
| } |
| |
| public boolean isDiscover() { |
| return tagType == ReaderTagType.DEFAULT && getTagSlug().equals(TAG_TITLE_DISCOVER); |
| } |
| |
| public boolean isTagTopic() { |
| String endpoint = getEndpoint(); |
| return endpoint.toLowerCase().contains("/read/tags/"); |
| } |
| public boolean isListTopic() { |
| String endpoint = getEndpoint(); |
| return endpoint.toLowerCase().contains("/read/list/"); |
| } |
| |
| /* |
| * the label is the text displayed in the dropdown filter |
| */ |
| @Override |
| public String getLabel() { |
| if (tagType == ReaderTagType.DEFAULT) { |
| return getTagTitle(); |
| } else if (isTagDisplayNameAlphaNumeric()) { |
| return getTagDisplayName().toLowerCase(); |
| } else if (hasTagTitle()) { |
| return getTagTitle(); |
| } else { |
| return getTagDisplayName(); |
| } |
| } |
| |
| /* |
| * returns true if the tag display name contains only alpha-numeric characters or hyphens |
| */ |
| private boolean isTagDisplayNameAlphaNumeric() { |
| if (TextUtils.isEmpty(tagDisplayName)) { |
| return false; |
| } |
| |
| for (int i=0; i < tagDisplayName.length(); i++) { |
| char c = tagDisplayName.charAt(i); |
| if (!Character.isLetterOrDigit(c) && c != '-') { |
| return false; |
| } |
| } |
| |
| return true; |
| } |
| |
| @Override |
| public boolean equals(Object object){ |
| if (object instanceof ReaderTag) { |
| ReaderTag tag = (ReaderTag) object; |
| return (tag.tagType == this.tagType && tag.getLabel().equals(this.getLabel())); |
| } else { |
| return false; |
| } |
| } |
| } |