package edu.washington.geopost; import java.util.HashSet; import java.util.List; import java.util.Set; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.util.Log; import com.google.android.gms.maps.model.LatLng; import com.parse.ParseException; import com.parse.ParseFile; import com.parse.ParseGeoPoint; import com.parse.ParseQuery; import com.parse.ParseRelation; import com.parse.ParseUser; /** * DBQuery retrieves information from the Parse database using parameterized * queries. * * @authors Katie Madonna, Andrew Repp, Megan Drasnin */ public class DBQuery { /** * Returns all of the pins located within the geographical box bounded by * the given corners. * @param southWest The lower left corner of the box for which pins are * desired * @param northEast The upper right corner of the box for which pins are * desired * @return A set of the Pins within the given box, or null if there is an * error fetching data */ public Set<Pin> getPins(LatLng southWest, LatLng northEast) { // Convert the given Locations to ParseGeoPoints for the query ParseGeoPoint sw = new ParseGeoPoint(southWest.latitude, southWest.longitude); ParseGeoPoint ne = new ParseGeoPoint(northEast.latitude, northEast.longitude); // Set up the ParseQuery for the pins within the given coordinates ParseQuery<ParsePin> pinQuery = ParseQuery.getQuery(ParsePin.class); pinQuery.include("user"); pinQuery.whereWithinGeoBox("location", sw, ne); // Get the results of the query List<ParsePin> queryResults = null; try { queryResults = pinQuery.find(); } catch (ParseException e) { // Fetching pins had an error return null; } // If we reached this point, then we know that we successfully // retrieved the pin data from the database. Therefore, we fetch the // current user and set up the query for the list of pins they've // viewed inside the bounding box. ParseUser user = ParseUser.getCurrentUser(); if (user == null) { return new HashSet<Pin>(); } ParseRelation<ParsePin> viewedRelation = user.getRelation("viewed"); ParseQuery<ParsePin> viewedQuery = viewedRelation.getQuery(); viewedQuery.whereWithinGeoBox("location", sw, ne); // Execute the query List<ParsePin> viewed = null; try { viewed = viewedQuery.find(); } catch (ParseException e) { // Fetching viewed had an error return null; } // If we reached this point, then we know that we successfully // retrieved all of the pin data from the database. Therefore, we // process the data to build up our final result. Log.d("getPins", "All pins: " + queryResults); Log.d("getPins", "My pins : " + viewed); // The set that we return Set<Pin> pinsToDisplay = new HashSet<Pin>(); // Go over each ParsePin in the result and convert it into an // appropriate Pin object for the map. for (ParsePin pin : queryResults) { // If this pin is in the user's list of viewed pins, then we'll // mark the pin as unlocked. Otherwise, we'll set it as locked. boolean locked = !viewed.contains(pin); Log.d("getPins", pin + " " + locked); // Set up the pin's location. LatLng location = new LatLng(pin.getLocation().getLatitude(), pin.getLocation().getLongitude()); // Get the pin's original poster and their Facebook ID if (pin.getUser() == null) { Log.d("getPins", "pin.getUser() is null"); // If the pin's getUser is null, it will crash // when trying to find facebook ID. This could happen // when we mess with database manually and accidentally // delete a user who has pins continue; } String poster = pin.getUser().getUsername(); String facebookID = pin.getUser().getString("facebookID"); // Get the pin's photo if it has one ParseFile photoFile = pin.getParseFile("photo"); Bitmap photo = null; boolean photoSuccessful = true; // true if no photo or photo // successfully obtained from // database, false otherwise if (photoFile != null) { byte[] photoData; try { photoData = photoFile.getData(); photo = BitmapFactory.decodeByteArray(photoData, 0, photoData.length); } catch (ParseException e) { // There was an error reading the ParseFile, so we can't // include the photo in the returned Pin. We set the // boolean to false so that we don't include the Pin in the // set of returned pins. Log.d("PHOTO", "Couldn't read data from ParseFile"); photoSuccessful = false; } } if (photoSuccessful) { // Make the new Pin and add it to the result set Pin newPin = new Pin(locked, location, poster, facebookID, pin.getObjectId(), pin.getMessage(), photo); pinsToDisplay.add(newPin); } } return pinsToDisplay; } /** * Returns a User object containing information about the current user of * the app. * @return The User about which information is desired, or null if there is * an error fetching the data */ public User getCurrentUser() { String name = null; String facebookID = null; int viewedNum = 0; int postedNum = 0; // Fetch the current user's name and FacebookID ParseUser user = ParseUser.getCurrentUser(); if (user == null) { return null; } name = user.getUsername(); facebookID = user.getString("facebookID"); // Get the number of pins they've viewed ParseRelation<ParsePin> viewedRelation = user.getRelation("viewed"); try { viewedNum = viewedRelation.getQuery().count(); } catch (ParseException e) { // Error fetching viewed return null; } // Get the number of pins they've posted ParseRelation<ParsePin> postedRelation = user.getRelation("posted"); try { postedNum = postedRelation.getQuery().count(); } catch (ParseException e) { // Error fetching posted return null; } return new User(viewedNum, postedNum, name, facebookID); } /** * Returns a set containing the Facebook IDs of the current user's * friends that are signed up for GeoPost. * * @return A Set<String> containing the Facebook IDs of the current user's * friends that are signed up for GeoPost, or null if there is an * error fetching the data */ public Set<String> getFriends() { Set<String> friendIDs = new HashSet<String>(); // Get a list of the ParseUsers with which the current user is friends ParseUser currentUser = ParseUser.getCurrentUser(); if (currentUser == null) { return friendIDs; } ParseRelation<ParseUser> friendsRelation = currentUser.getRelation("friends"); ParseQuery<ParseUser> friendsQuery = friendsRelation.getQuery(); List<ParseUser> friends = null; try { friends = friendsQuery.find(); } catch (ParseException e) { // Error fetching the user's friends return null; } // fill and return the Set of Facebook IDs for (ParseUser friend : friends) { friendIDs.add(friend.getString("facebookID")); } return friendIDs; } }