/*
* Copyright 2014 Google Inc. All rights reserved.
*
* 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 com.google.samples.apps.iosched.model;
import android.content.Context;
import android.content.CursorLoader;
import android.database.Cursor;
import android.provider.BaseColumns;
import android.text.TextUtils;
import com.google.samples.apps.iosched.Config;
import com.google.samples.apps.iosched.archframework.QueryEnum;
import com.google.samples.apps.iosched.provider.ScheduleContract;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
public class TagMetadata {
// List of tags in each category, sorted by the category sort order.
private HashMap<String, ArrayList<Tag>> mTagsInCategory = new HashMap<String, ArrayList<Tag>>();
// Hash map from tag ID to tag.
private HashMap<String, Tag> mTagsById = new HashMap<String, Tag>();
// Hash map from tag name to tag id.
private HashMap<String, String> mTagsByName = new HashMap<String, String>();
public static CursorLoader createCursorLoader(Context context) {
return new CursorLoader(context, ScheduleContract.Tags.CONTENT_URI,
TagsQueryEnum.TAG.getProjection(), null, null, null);
}
protected TagMetadata() {
}
public TagMetadata(Cursor cursor) {
// Not using while(cursor.moveToNext()) because it would lead to issues when writing tests.
// Either we would mock cursor.moveToNext() to return true and the test would have infinite
// loop, or we would mock cursor.moveToNext() to return false, and the test would be for an
// empty cursor.
int count = cursor.getCount();
for (int i = 0; i < count; i++) {
cursor.moveToPosition(i);
Tag tag = new Tag(cursor.getString(cursor.getColumnIndex(ScheduleContract.Tags.TAG_ID)),
cursor.getString(cursor.getColumnIndex(ScheduleContract.Tags.TAG_NAME)),
cursor.getString(cursor.getColumnIndex(ScheduleContract.Tags.TAG_CATEGORY)),
cursor.getInt(
cursor.getColumnIndex(ScheduleContract.Tags.TAG_ORDER_IN_CATEGORY)),
cursor.getString(cursor.getColumnIndex(ScheduleContract.Tags.TAG_ABSTRACT)),
cursor.getInt(cursor.getColumnIndex(ScheduleContract.Tags.TAG_COLOR)),
cursor.getString(cursor.getColumnIndex(ScheduleContract.Tags.TAG_PHOTO_URL)));
mTagsById.put(tag.getId(), tag);
mTagsByName.put(tag.getName(), tag.getId());
if (!mTagsInCategory.containsKey(tag.getCategory())) {
mTagsInCategory.put(tag.getCategory(), new ArrayList<Tag>());
}
mTagsInCategory.get(tag.getCategory()).add(tag);
}
for (ArrayList<Tag> list : mTagsInCategory.values()) {
Collections.sort(list);
}
}
/**
* @return the tag with the {@code tagId}, if found.
*/
public Tag getTagById(String tagId) {
return mTagsById.containsKey(tagId) ? mTagsById.get(tagId) : null;
}
/**
* @return the tag with the {@code tagName} if found.
*/
private Tag getTagByName(String tagName) {
String tagId = mTagsByName.containsKey(tagName) ? mTagsByName.get(tagName) : null;
return tagId != null ? getTagById(tagId) : null;
}
/**
* @return the tag with the id matching the {@code searchString}, if found; if not found,
* returns the tag with the name matching the {@code searchString}, if found.
*/
public Tag getTag(String searchString) {
Tag tagById = getTagById(searchString);
if (tagById != null) {
return tagById;
} else {
return getTagByName(searchString);
}
}
public List<Tag> getTagsInCategory(String category) {
return mTagsInCategory.containsKey(category) ?
Collections.unmodifiableList(mTagsInCategory.get(category)) : null;
}
/**
* Given the set of tags on a session, returns its group label.
*/
public Tag getSessionGroupTag(String[] sessionTags) {
int bestOrder = Integer.MAX_VALUE;
Tag bestTag = null;
for (String tagId : sessionTags) {
Tag tag = getTagById(tagId);
if (tag != null &&
Config.Tags.SESSION_GROUPING_TAG_CATEGORY.equals(tag.getCategory()) &&
tag.getOrderInCategory() < bestOrder) {
bestOrder = tag.getOrderInCategory();
bestTag = tag;
}
}
return bestTag;
}
@Override
public String toString() {
return "Tag Metadata has " + mTagsById.size() + " tags in " + mTagsInCategory.size()
+ " categories";
}
public static Comparator<Tag> TAG_DISPLAY_ORDER_COMPARATOR = new Comparator<Tag>() {
@Override
public int compare(Tag tag, Tag tag2) {
if (!TextUtils.equals(tag.getCategory(), tag2.getCategory())) {
return Config.getCategoryDisplayOrder(tag.getCategory()) -
Config.getCategoryDisplayOrder(tag2.getCategory());
} else if (tag.getOrderInCategory() != tag2.getOrderInCategory()) {
return tag.getOrderInCategory() - tag2.getOrderInCategory();
}
return tag.getName().compareTo(tag2.getName());
}
};
public enum TagsQueryEnum implements QueryEnum {
TAG(0, new String[]{
BaseColumns._ID,
ScheduleContract.Tags.TAG_ID,
ScheduleContract.Tags.TAG_NAME,
ScheduleContract.Tags.TAG_CATEGORY,
ScheduleContract.Tags.TAG_ORDER_IN_CATEGORY,
ScheduleContract.Tags.TAG_ABSTRACT,
ScheduleContract.Tags.TAG_COLOR,
ScheduleContract.Tags.TAG_PHOTO_URL
});
private int id;
private String[] projection;
TagsQueryEnum(int id, String[] projection) {
this.id = id;
this.projection = projection;
}
@Override
public int getId() {
return id;
}
@Override
public String[] getProjection() {
return projection;
}
}
static public class Tag implements Comparable<Tag> {
private String mId;
private String mName;
private String mCategory;
private int mOrderInCategory;
private String mAbstract;
private int mColor;
private String mPhotoUrl;
public Tag(String id, String name, String category, int orderInCategory, String _abstract,
int color, String photoUrl) {
mId = id;
mName = name;
mCategory = category;
mOrderInCategory = orderInCategory;
mAbstract = _abstract;
mColor = color;
mPhotoUrl = photoUrl;
}
public String getId() {
return mId;
}
public String getName() {
return mName;
}
public String getCategory() {
return mCategory;
}
public int getOrderInCategory() {
return mOrderInCategory;
}
public String getAbstract() {
return mAbstract;
}
public int getColor() {
return mColor;
}
public String getPhotoUrl() {
return mPhotoUrl;
}
@Override
public int compareTo(Tag another) {
return mOrderInCategory - another.mOrderInCategory;
}
@Override
public String toString() {
return "TagMetadata.Tag: id = " + mId + " name = " + mName;
}
}
}