package com.nilhcem.bblfr.model.baggers.dao; import android.support.annotation.NonNull; import com.nilhcem.bblfr.model.baggers.Bagger; import com.nilhcem.bblfr.model.baggers.BaggerCity; import com.nilhcem.bblfr.model.baggers.City; import com.nilhcem.bblfr.model.baggers.Contact; import com.nilhcem.bblfr.model.baggers.Session; import com.nilhcem.bblfr.model.baggers.SessionTag; import com.nilhcem.bblfr.model.baggers.Tag; import com.nilhcem.bblfr.model.baggers.Website; import java.util.ArrayList; import java.util.List; import javax.inject.Inject; import javax.inject.Singleton; import ollie.query.Select; import ollie.util.QueryUtils; @Singleton public class BaggersDao { @Inject public BaggersDao() { } public boolean hasData() { return Select.from(Bagger.class).fetchSingle() != null; } /** * Gets all the baggers matching specified tags (if any) for a given city. */ public List<Bagger> getBaggers(@NonNull Long cityId, @NonNull List<String> tagsIds) { List<String> args = new ArrayList<>(); args.add(Long.toString(cityId)); int nbTags = tagsIds.size(); StringBuilder sql = new StringBuilder("SELECT DISTINCT baggers.* FROM baggers INNER JOIN baggers_cities ON baggers._id=baggers_cities.bagger_id"); if (nbTags > 0) { sql.append(" INNER JOIN sessions ON baggers._id=sessions.bagger_id INNER JOIN sessions_tags ON sessions._id=sessions_tags.session_id"); } sql.append(" WHERE baggers_cities.city_id=?"); if (nbTags > 0) { sql.append(" AND sessions_tags.tag_id IN ("); boolean addSeparator = false; for (String tagId : tagsIds) { if (addSeparator) { sql.append(","); } else { addSeparator = true; } sql.append("?"); args.add(tagId); } sql.append(")"); } sql.append(" ORDER BY RANDOM()"); List<Bagger> baggers = QueryUtils.rawQuery(Bagger.class, sql.toString(), args.toArray(new String[args.size()])); for (Bagger bagger : baggers) { fillBaggerData(bagger, tagsIds); } return baggers; } private void fillBaggerData(@NonNull Bagger bagger, @NonNull List<String> tagsIds) { // contacts bagger.contacts = Select.from(Contact.class).where("contacts.bagger_id=?", bagger.id).fetchSingle(); if (bagger.contacts == null) { bagger.contacts = new Contact(); } // cities List<City> cities = Select.from(City.class).innerJoin(BaggerCity.class).on("cities._id=baggers_cities.city_id").where("baggers_cities.bagger_id=?", bagger.id).fetch(); bagger.cities = new ArrayList<>(); for (City city : cities) { bagger.cities.add(city.name); } // sessions List<Session> sessions = Select.from(Session.class).where("bagger_id=?", bagger.id).fetch(); for (Session session : sessions) { List<Tag> tags = Select.from(Tag.class).innerJoin(SessionTag.class).on("tags._id=sessions_tags.tag_id").where("sessions_tags.session_id=?", session.id).fetch(); session.tags = new ArrayList<>(); for (Tag tag : tags) { session.tags.add(tag.name); } } bagger.sessions = filterSessionsMatchingTags(sessions, tagsIds); // websites bagger.websites = Select.from(Website.class).where("bagger_id=?", bagger.id).fetch(); } /** * Gets all the sessions tags for a specified city, sorted by tags popularity. */ public List<Tag> getSessionsTags(@NonNull Long cityId) { String sql = "SELECT DISTINCT tags.* FROM sessions_tags INNER JOIN tags ON sessions_tags.tag_id=tags._id INNER JOIN sessions ON sessions_tags.session_id=sessions._id INNER JOIN baggers_cities ON sessions.bagger_id=baggers_cities.bagger_id WHERE baggers_cities.city_id=? GROUP BY sessions_tags.tag_id ORDER BY COUNT(sessions_tags.tag_id) DESC"; return QueryUtils.rawQuery(Tag.class, sql, new String[]{Long.toString(cityId)}); } private List<Session> filterSessionsMatchingTags(@NonNull List<Session> sessions, @NonNull List<String> tagsIds) { if (tagsIds.isEmpty()) { return sessions; } List<Session> filtered = new ArrayList<>(); List<String> tags = getTagsNamesPerIds(tagsIds); for (Session session : sessions) { for (String tag : tags) { if (session.tags.contains(tag)) { filtered.add(session); break; } } } return filtered; } private List<String> getTagsNamesPerIds(@NonNull List<String> tagsIds) { boolean addSeparator = false; List<String> args = new ArrayList<>(); StringBuilder whereStr = new StringBuilder("_id IN ("); for (String tagId : tagsIds) { if (addSeparator) { whereStr.append(","); } else { addSeparator = true; } whereStr.append("?"); args.add(tagId); } whereStr.append(")"); List<Tag> tags = Select.from(Tag.class).where(whereStr.toString(), args.toArray(new String[args.size()])).fetch(); List<String> tagsNames = new ArrayList<>(tags.size()); for (Tag tag : tags) { tagsNames.add(tag.name); } return tagsNames; } }