001/** 002 * Copyright 2014 Tampere University of Technology, Pori Department 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package service.tut.pori.facebookjazz.reference; 017 018import java.util.List; 019 020import org.apache.commons.lang3.StringUtils; 021import org.apache.http.client.methods.HttpPost; 022import org.apache.http.entity.StringEntity; 023import org.apache.log4j.Logger; 024 025import service.tut.pori.contentanalysis.AbstractTaskDetails; 026import service.tut.pori.contentanalysis.AsyncTask.TaskStatus; 027import service.tut.pori.contentanalysis.AsyncTask.TaskType; 028import service.tut.pori.contentanalysis.PhotoList; 029import service.tut.pori.contentanalysis.PhotoTaskResponse; 030import service.tut.pori.contentanalysis.MediaObjectList; 031import service.tut.pori.contentanalysis.reference.CAReferenceCore; 032import service.tut.pori.contentanalysis.reference.CAXMLObjectCreator; 033import service.tut.pori.facebookjazz.Definitions; 034import service.tut.pori.facebookjazz.FBFeedbackTaskDetails; 035import service.tut.pori.facebookjazz.FBSummarizationTaskDetails; 036import service.tut.pori.facebookjazz.FBTaskResponse; 037import service.tut.pori.facebookjazz.FacebookComment; 038import service.tut.pori.facebookjazz.FacebookEvent; 039import service.tut.pori.facebookjazz.FacebookExtractor.ContentType; 040import service.tut.pori.facebookjazz.FacebookGroup; 041import service.tut.pori.facebookjazz.FacebookLike; 042import service.tut.pori.facebookjazz.FacebookLocation; 043import service.tut.pori.facebookjazz.FacebookPhotoDescription; 044import service.tut.pori.facebookjazz.FacebookPhotoTag; 045import service.tut.pori.facebookjazz.FacebookProfile; 046import service.tut.pori.facebookjazz.FacebookRelationship; 047import service.tut.pori.facebookjazz.FacebookStatusMessage; 048import service.tut.pori.facebookjazz.FacebookUserDetails; 049import service.tut.pori.facebookjazz.FacebookVideoDescription; 050import service.tut.pori.facebookjazz.WeightModifier; 051import service.tut.pori.facebookjazz.WeightModifierList; 052import core.tut.pori.http.parameters.DataGroups; 053import core.tut.pori.http.parameters.Limits; 054import core.tut.pori.http.parameters.SortOptions; 055import core.tut.pori.users.UserIdentity; 056import core.tut.pori.utils.XMLFormatter; 057 058/** 059 * The reference implementations for FacebookJazz Service. 060 * 061 */ 062public final class FBJReferenceCore { 063 private static final FBJXMLObjectCreator CREATOR = new FBJXMLObjectCreator(null); 064 private static final DataGroups DATAGROUPS_BACKEND_RESPONSE = new DataGroups(CAXMLObjectCreator.DATA_GROUP_BACKEND_RESPONSE); // data groups for add task callback 065 private static final Limits DEFAULT_LIMITS = new Limits(0, 0); // default number of limits for references 066 private static final Logger LOGGER = Logger.getLogger(FBJReferenceCore.class); 067 068 /** 069 * 070 */ 071 private FBJReferenceCore(){ 072 // nothing needed 073 } 074 075 /** 076 * 077 * @param authenticatedUser 078 * @param dataGroups 079 * @param limits only the amount of results is processed for the limits. This is because the results are randomly generated, and thus have no 080 * order which could be used for paging. 081 * @param sortOptions sort options are ignored. This is because of the complexity of the sort operations performed for randomly generated data. 082 * @return example list of media objects for the given values 083 */ 084 public static MediaObjectList retrieveTagsForUser(UserIdentity authenticatedUser, DataGroups dataGroups, Limits limits, SortOptions sortOptions) { 085 LOGGER.info((authenticatedUser == null ? "No logged in user." : "Ignoring the logged in user, id: "+authenticatedUser.getUserId())); // only notify of the logged in status 086 return CREATOR.createTagList(CREATOR.createBackendId(), dataGroups, limits, authenticatedUser); 087 } 088 089 /** 090 * 091 * @param authenticatedUser 092 * @param ranks list of ranks in the form of rank=guid:VALUE,guid:VALUE,... 093 */ 094 public static void setRank(UserIdentity authenticatedUser, List<String> ranks) { 095 LOGGER.info((authenticatedUser == null ? "No logged in user." : "Ignoring the logged in user, id: "+authenticatedUser.getUserId())); // only notify of the logged in status 096 if(ranks == null || ranks.isEmpty()){ 097 throw new IllegalArgumentException("Failed to process rank parameter."); 098 } 099 100 for(String r : ranks){ 101 String[] parts = r.split(core.tut.pori.http.Definitions.SEPARATOR_URI_QUERY_TYPE_VALUE); 102 if(parts.length != 2){ 103 throw new IllegalArgumentException("Failed to process rank parameter: "+r); 104 } 105 } // for 106 } 107 108 /** 109 * 110 * @param response 111 */ 112 public static void taskFinished(PhotoTaskResponse response) { 113 Integer tBackendId = response.getBackendId(); 114 if(tBackendId == null){ 115 throw new IllegalArgumentException("Invalid backendId: "+tBackendId); 116 } 117 Long tTaskId = response.getTaskId(); 118 if(tTaskId == null){ 119 throw new IllegalArgumentException("Invalid taskId: "+tTaskId); 120 } 121 122 TaskStatus status = response.getStatus(); 123 if(status == null){ 124 throw new IllegalArgumentException("TaskStatus is invalid or missing."); 125 } 126 127 TaskType type = response.getTaskType(); 128 if(type == null){ 129 throw new IllegalArgumentException("TaskType is invalid or missing."); 130 } 131 132 try{ 133 switch(type){ 134 case FACEBOOK_PROFILE_SUMMARIZATION: 135 FBTaskResponse fr = (FBTaskResponse) response; 136 if(!PhotoList.isValid(fr.getPhotoList()) && !MediaObjectList.isValid(fr.getMediaObjects())){ 137 LOGGER.warn("No valid media object list or photo list."); 138 } 139 break; 140 case BACKEND_FEEDBACK: // should not have any content, so accept anything 141 break; 142 default: 143 throw new IllegalArgumentException("Tasks of type: "+type.name()+" are not supported by this validator."); 144 } 145 }catch(ClassCastException ex){ 146 LOGGER.debug(ex, ex); 147 throw new IllegalArgumentException("Task content data was not of the expected type."); 148 } 149 } 150 151 /** 152 * 153 * @param taskDetails 154 */ 155 public static void addTask(FBTaskDetails taskDetails) { 156 Integer tBackendId = taskDetails.getBackendId(); 157 if(tBackendId == null){ 158 throw new IllegalArgumentException("Invalid backendId: "+tBackendId); 159 } 160 Long tTaskId = taskDetails.getTaskId(); 161 if(tTaskId == null){ 162 throw new IllegalArgumentException("Invalid taskId: "+tTaskId); 163 } 164 165 String uri = taskDetails.getCallbackUri(); 166 if(StringUtils.isBlank(uri)){ 167 throw new IllegalArgumentException("Invalid callbackUri: "+uri); 168 } 169 170 TaskType type = taskDetails.getTaskType(); 171 if(type == null){ 172 throw new IllegalArgumentException("TaskType is invalid or missing."); 173 } 174 175 switch(type){ 176 case FACEBOOK_PROFILE_SUMMARIZATION: 177 if(taskDetails.getProfile() == null){ 178 throw new IllegalArgumentException("Invalid "+Definitions.ELEMENT_FACEBOOK_PROFILE); 179 } 180 addTaskAsyncCallback(taskDetails, CREATOR.createTagList(tBackendId, DATAGROUPS_BACKEND_RESPONSE, DEFAULT_LIMITS, taskDetails.getUserId())); 181 break; 182 case FACEBOOK_PROFILE_SUMMARIZATION_FEEDBACK: 183 if(!MediaObjectList.isValid(taskDetails.getTags())){ 184 LOGGER.warn("Invalid media object list."); 185 } 186 addTaskAsyncCallback(taskDetails, null); 187 break; 188 case BACKEND_FEEDBACK: 189 if(!PhotoList.isValid(taskDetails.getPhotoList())){ 190 throw new IllegalArgumentException("Invalid "+service.tut.pori.contentanalysis.Definitions.ELEMENT_PHOTOLIST); 191 } 192 addTaskAsyncCallback(taskDetails, null); 193 break; 194 default: 195 throw new IllegalArgumentException("Tasks of type: "+type.name()+" are not supported by this validator."); 196 } 197 } 198 199 /** 200 * Call asynchronously the callback given in the details, returning an example task response 201 * 202 * @param details 203 * @param mediaObjectList 204 * @see service.tut.pori.facebookjazz.FBTaskResponse 205 */ 206 public static void addTaskAsyncCallback(AbstractTaskDetails details, MediaObjectList mediaObjectList) { 207 HttpPost post = new HttpPost(details.getCallbackUri()); 208 FBTaskResponse r = new FBTaskResponse(); 209 r.setBackendId(details.getBackendId()); 210 r.setTaskId(details.getTaskId()); 211 r.setStatus(TaskStatus.COMPLETED); 212 r.setTaskType(details.getTaskType()); 213 r.setMediaObjects(mediaObjectList); 214 post.setEntity(new StringEntity((new XMLFormatter()).toString(r), core.tut.pori.http.Definitions.ENCODING_UTF8)); 215 216 CAReferenceCore.executeAsyncCallback(post); 217 } 218 219 /** 220 * 221 * @param authenticatedUser 222 * @param weightModifierList 223 */ 224 public static void setTagWeights(UserIdentity authenticatedUser, WeightModifierList weightModifierList) { 225 LOGGER.info((authenticatedUser == null ? "No logged in user." : "Ignoring the logged in user, id: "+authenticatedUser.getUserId())); // only notify of the logged in status 226 227 if(!WeightModifierList.isValid(weightModifierList)){ 228 throw new IllegalArgumentException("Invalid "+Definitions.ELEMENT_WEIGHT_MODIFIER_LIST+"."); 229 } 230 } 231 232 /** 233 * 234 * @param authenticatedUser 235 * @param userId 236 * @return example list of weights for the given values 237 */ 238 public static WeightModifierList retrieveTagWeights(UserIdentity authenticatedUser, Long userId) { 239 LOGGER.info((authenticatedUser == null ? "No logged in user, with user id filter: "+userId : "Ignoring the logged in user, id: "+authenticatedUser.getUserId()+", with user id filter: "+userId)); // only notify of the logged in status 240 return CREATOR.createWeightModifierList(); 241 } 242 243 /** 244 * 245 * @param authenticatedUser 246 * @param contentTypes 247 * @param synchronize 248 */ 249 public static void summarize(UserIdentity authenticatedUser, List<String> contentTypes, boolean synchronize) { 250 LOGGER.info((authenticatedUser == null ? "No logged in user." : "Ignoring the logged in user, id: "+authenticatedUser.getUserId())); // only notify of the logged in status 251 ContentType.fromString(contentTypes); // throws an exception on invalid values 252 } 253 254 /** 255 * 256 * @return randomly generated weihgt modifier list 257 */ 258 public static WeightModifierList generateWeighModifierList() { 259 return CREATOR.createWeightModifierList(); 260 } 261 262 /** 263 * 264 * @param limits 265 * @return randomly generated task response 266 */ 267 public static FBTaskResponse generateTaskResponse(Limits limits) { 268 return CREATOR.createTaskResponse(DATAGROUPS_BACKEND_RESPONSE, limits, null, TaskType.FACEBOOK_PROFILE_SUMMARIZATION); 269 } 270 271 /** 272 * 273 * @param limits 274 * @return randomly generated task details 275 */ 276 public static FBSummarizationTaskDetails generateFBSummarizationTaskDetails(Limits limits) { 277 int likeCount = limits.getMaxItems(Definitions.ELEMENT_LIKE_LIST); 278 if(likeCount >= Limits.DEFAULT_MAX_ITEMS){ 279 LOGGER.debug("Reseting limits for "+Definitions.ELEMENT_LIKE_LIST+": max items was "+Limits.DEFAULT_MAX_ITEMS); 280 likeCount = DEFAULT_LIMITS.getMaxItems(Definitions.ELEMENT_LIKE_LIST); 281 } 282 int eventCount = limits.getMaxItems(Definitions.ELEMENT_EVENT_LIST); 283 if(eventCount >= Limits.DEFAULT_MAX_ITEMS){ 284 LOGGER.debug("Reseting limits for "+Definitions.ELEMENT_EVENT_LIST+": max items was "+Limits.DEFAULT_MAX_ITEMS); 285 eventCount = DEFAULT_LIMITS.getMaxItems(Definitions.ELEMENT_EVENT_LIST); 286 } 287 int groupCount = limits.getMaxItems(Definitions.ELEMENT_GROUP_LIST); 288 if(groupCount >= Limits.DEFAULT_MAX_ITEMS){ 289 LOGGER.debug("Reseting limits for "+Definitions.ELEMENT_GROUP_LIST+": max items was "+Limits.DEFAULT_MAX_ITEMS); 290 groupCount = DEFAULT_LIMITS.getMaxItems(Definitions.ELEMENT_GROUP_LIST); 291 } 292 int photoDescriptionCount = limits.getMaxItems(Definitions.ELEMENT_PHOTO_DESCRIPTION_LIST); 293 if(photoDescriptionCount >= Limits.DEFAULT_MAX_ITEMS){ 294 LOGGER.debug("Reseting limits for "+Definitions.ELEMENT_PHOTO_DESCRIPTION_LIST+": max items was "+Limits.DEFAULT_MAX_ITEMS); 295 photoDescriptionCount = DEFAULT_LIMITS.getMaxItems(Definitions.ELEMENT_PHOTO_DESCRIPTION_LIST); 296 } 297 int videoDescriptionCount = limits.getMaxItems(Definitions.ELEMENT_VIDEO_DESCRIPTION_LIST); 298 if(videoDescriptionCount >= Limits.DEFAULT_MAX_ITEMS){ 299 LOGGER.debug("Reseting limits for "+Definitions.ELEMENT_VIDEO_DESCRIPTION_LIST+": max items was "+Limits.DEFAULT_MAX_ITEMS); 300 videoDescriptionCount = DEFAULT_LIMITS.getMaxItems(Definitions.ELEMENT_VIDEO_DESCRIPTION_LIST); 301 } 302 int statusMessageCount = limits.getMaxItems(Definitions.ELEMENT_STATUS_MESSAGE_LIST); 303 if(statusMessageCount >= Limits.DEFAULT_MAX_ITEMS){ 304 LOGGER.debug("Reseting limits for "+Definitions.ELEMENT_STATUS_MESSAGE_LIST+": max items was "+Limits.DEFAULT_MAX_ITEMS); 305 statusMessageCount = DEFAULT_LIMITS.getMaxItems(Definitions.ELEMENT_STATUS_MESSAGE_LIST); 306 } 307 int tagCount = limits.getMaxItems(Definitions.ELEMENT_PHOTO_TAG_LIST); 308 if(tagCount >= Limits.DEFAULT_MAX_ITEMS){ 309 LOGGER.debug("Reseting limits for "+Definitions.ELEMENT_PHOTO_TAG_LIST+": max items was "+Limits.DEFAULT_MAX_ITEMS); 310 tagCount = DEFAULT_LIMITS.getMaxItems(Definitions.ELEMENT_PHOTO_TAG_LIST); 311 } 312 int commentCount = limits.getMaxItems(Definitions.ELEMENT_COMMENT_LIST); 313 if(commentCount >= Limits.DEFAULT_MAX_ITEMS){ 314 LOGGER.debug("Reseting limits for "+Definitions.ELEMENT_COMMENT_LIST+": max items was "+Limits.DEFAULT_MAX_ITEMS); 315 commentCount = DEFAULT_LIMITS.getMaxItems(Definitions.ELEMENT_COMMENT_LIST); 316 } 317 return CREATOR.createFBSummarizationTaskDetails(likeCount, eventCount, groupCount, photoDescriptionCount, videoDescriptionCount, statusMessageCount, tagCount, commentCount); 318 } 319 320 /** 321 * 322 * @param limits 323 * @return randomly generated task details 324 */ 325 public static FBFeedbackTaskDetails generateFBFeedbackTaskDetails(Limits limits) { 326 int objectCount = limits.getMaxItems(service.tut.pori.contentanalysis.Definitions.ELEMENT_MEDIA_OBJECTLIST); 327 if(objectCount >= Limits.DEFAULT_MAX_ITEMS){ 328 LOGGER.debug("Reseting limits for "+service.tut.pori.contentanalysis.Definitions.ELEMENT_MEDIA_OBJECTLIST+": max items was "+Limits.DEFAULT_MAX_ITEMS); 329 objectCount = DEFAULT_LIMITS.getMaxItems(service.tut.pori.contentanalysis.Definitions.ELEMENT_MEDIA_OBJECTLIST); 330 } 331 332 return CREATOR.createFBFeedbackTaskDetails(objectCount); 333 } 334 335 /** 336 * 337 * @return randomly generated photo tag 338 */ 339 public static FacebookPhotoTag generateFacebookPhotoTag() { 340 return CREATOR.createFacebookPhotoTag(); 341 } 342 343 /** 344 * 345 * @return randomly generated weight modifier 346 */ 347 public static WeightModifier generateWeighModifier() { 348 return CREATOR.createWeightModifier(null); 349 } 350 351 /** 352 * 353 * @return randomly generated comment 354 */ 355 public static FacebookComment generateFacebookComment() { 356 return CREATOR.createComment(); 357 } 358 359 /** 360 * 361 * @return randomly generated event 362 */ 363 public static FacebookEvent generateFacebookEvent() { 364 return CREATOR.createFacebookEvent(); 365 } 366 367 /** 368 * 369 * @return randomly generated group 370 */ 371 public static FacebookGroup generateFacebookGroup() { 372 return CREATOR.createFacebookGroup(); 373 } 374 375 /** 376 * 377 * @return randomly generated location 378 */ 379 public static FacebookLocation generateFacebookLocation() { 380 return CREATOR.createFacebookLocation(); 381 } 382 383 /** 384 * 385 * @return randomly generated description 386 */ 387 public static FacebookPhotoDescription generateFacebookPhotoDescription() { 388 return CREATOR.createFacebookPhotoDescription(DEFAULT_LIMITS.getMaxItems(Definitions.ELEMENT_COMMENT_LIST), DEFAULT_LIMITS.getMaxItems(Definitions.ELEMENT_PHOTO_TAG_LIST)); 389 } 390 391 /** 392 * 393 * @return randomly generated profile 394 */ 395 public static FacebookProfile generateFacebookProfile() { 396 return CREATOR.createFacebookProfile(DEFAULT_LIMITS.getMaxItems(Definitions.ELEMENT_LIKE_LIST), DEFAULT_LIMITS.getMaxItems(Definitions.ELEMENT_EVENT_LIST), DEFAULT_LIMITS.getMaxItems(Definitions.ELEMENT_GROUP_LIST), DEFAULT_LIMITS.getMaxItems(Definitions.ELEMENT_PHOTO_DESCRIPTION_LIST), DEFAULT_LIMITS.getMaxItems(Definitions.ELEMENT_VIDEO_DESCRIPTION_LIST), DEFAULT_LIMITS.getMaxItems(Definitions.ELEMENT_STATUS_MESSAGE_LIST), DEFAULT_LIMITS.getMaxItems(Definitions.ELEMENT_PHOTO_TAG_LIST), DEFAULT_LIMITS.getMaxItems(Definitions.ELEMENT_COMMENT_LIST)); 397 } 398 399 /** 400 * 401 * @return randomly generated profile 402 */ 403 public static FacebookRelationship generateFacebookRelationship() { 404 return CREATOR.createFacebookRelationship(); 405 } 406 407 /** 408 * 409 * @return randomly generated status message 410 */ 411 public static FacebookStatusMessage generateFacebookStatusMessage() { 412 return CREATOR.createFacebookStatusMessage(DEFAULT_LIMITS.getMaxItems(Definitions.ELEMENT_COMMENT_LIST)); 413 } 414 415 /** 416 * 417 * @return randomly generated user details 418 */ 419 public static FacebookUserDetails generateFacebookUserDetails() { 420 return CREATOR.createFacebookUserDetails(); 421 } 422 423 /** 424 * 425 * @return randomly generated video description 426 */ 427 public static FacebookVideoDescription generateFacebookVideoDescription() { 428 return CREATOR.createFacebookVideoDescription(DEFAULT_LIMITS.getMaxItems(Definitions.ELEMENT_COMMENT_LIST)); 429 } 430 431 /** 432 * 433 * @return randomly generated like 434 */ 435 public static FacebookLike generateFacebookLike() { 436 return CREATOR.createFacebookLike(); 437 } 438}