private Map<String, Object> recursiveGrabber(
     OdklRequest request, String userId, Map<String, Object> fullMap) {
   try {
     String response = api.sendRequest(request);
     JSONObject responseJson = JsonUtil.parseObject(response);
     Map<String, Object> grabberTemp = grabber(userId, responseJson);
     if (grabberTemp != null) {
       if (fullMap == null) {
         fullMap = grabberTemp;
       } else {
         fullMap = appendMap(fullMap, grabberTemp);
       }
     }
     if ((Boolean) responseJson.get("hasMore")) {
       String anchor = (String) responseJson.get("anchor");
       return recursiveGrabber(request.addParam("anchor", anchor), userId, fullMap);
     }
     return fullMap;
   } catch (OdklApiRuntimeException e) {
     if (LOGS) {
       System.out.println(
           String.format(
               "[ERR][uid%s] Runtime error while loading profile. Connection failed.", userId));
     }
   }
   return null;
 }
 private JSONArray getAllMarksFromPhoto(String photoId) {
   try {
     OdklRequest request = api.createApiRequest("photos", "getTags").addParam("photo_id", photoId);
     String response = api.sendRequest(request);
     JSONObject responseJson = JsonUtil.parseObject(response);
     JSONArray marksArray = JsonUtil.getArray(responseJson, "photo_tags");
     return marksArray.isEmpty() ? null : marksArray;
   } catch (OdklApiRuntimeException e) {
     if (LOGS) {
       System.out.println(
           String.format(
               "[ERR][] Runtime error while loading marks from photo %s. Connection failed.",
               photoId));
     }
   }
   return null;
 }
 private List<String> recursiveGetPhotoList(
     OdklRequest request, String userId, List<String> fullList) {
   try {
     JSONObject responseJson = JsonUtil.parseObject(api.sendRequest(request));
     if (fullList == null) fullList = grabList(responseJson);
     else {
       fullList.addAll(grabList(responseJson));
     }
     if ((Boolean) responseJson.get("hasMore")) {
       String anchor = (String) responseJson.get("anchor");
       return recursiveGetPhotoList(request.addParam("anchor", anchor), userId, fullList);
     }
     return fullList;
   } catch (OdklApiRuntimeException e) {
     if (LOGS) {
       System.out.println(
           String.format(
               "[ERR][uid%s] Runtime error while loading photo list of the album. Connection failed.",
               userId));
     }
   }
   return null;
 }
 private List<String> getUserAlbumIds(String userId) {
   try {
     OdklRequest request =
         api.createApiRequest("photos", "getAlbums")
             .addParam("fid", userId)
             .addParam("count", "100");
     JSONObject responseJson = JsonUtil.parseObject(api.sendRequest(request));
     JSONArray albumArray = JsonUtil.getArray(responseJson, "albums");
     List<String> albumIds = new ArrayList<String>();
     for (int i = 0; i < albumArray.size(); i++) {
       JSONObject album = (JSONObject) albumArray.get(i);
       albumIds.add(JsonUtil.getString(album, "aid"));
     }
     return albumIds;
   } catch (OdklApiRuntimeException e) {
     if (LOGS) {
       System.out.println(
           String.format(
               "[ERR][uid%s] Runtime error while loading user albums list. Connection failed.",
               userId));
     }
   }
   return null;
 }
 private String getPhotoUrl(String photoId) {
   OdklRequest request =
       api.createApiRequest("photos", "getPhotoInfo").addParam("photo_id", photoId);
   JSONObject responseJson = JsonUtil.parseObject(api.sendRequest(request));
   return JsonUtil.getString(((JSONObject) responseJson.get("photo")), "pic640x480");
 }