001/** 002 * Copyright 2015 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.fuzzyvisuals; 017 018import java.io.IOException; 019import java.util.ArrayList; 020import java.util.Collections; 021import java.util.Iterator; 022import java.util.List; 023import java.util.Random; 024import java.util.Set; 025 026import org.apache.commons.lang3.StringUtils; 027import org.apache.http.client.methods.HttpPost; 028import org.apache.http.entity.StringEntity; 029import org.apache.http.impl.client.BasicResponseHandler; 030import org.apache.http.impl.client.CloseableHttpClient; 031import org.apache.http.impl.client.HttpClients; 032import org.apache.log4j.Logger; 033 034import service.tut.pori.contentanalysis.AsyncTask.TaskStatus; 035import service.tut.pori.contentanalysis.AsyncTask.TaskType; 036import service.tut.pori.contentanalysis.Definitions; 037import service.tut.pori.contentanalysis.MediaObject; 038import service.tut.pori.contentanalysis.MediaObject.ConfirmationStatus; 039import service.tut.pori.contentanalysis.MediaObject.MediaObjectType; 040import core.tut.pori.context.ServiceInitializer; 041import core.tut.pori.utils.HTTPHeaderUtil; 042import core.tut.pori.utils.MediaUrlValidator.MediaType; 043import core.tut.pori.utils.XMLFormatter; 044 045/** 046 * Simple runnable for executing FuzzyAnalysisTask 047 * 048 * Assumes that the given task is of type {@link service.tut.pori.contentanalysis.AsyncTask.TaskType#ANALYSIS} 049 * 050 */ 051public class FuzzyAnalysisTask implements Runnable { 052 private static final Logger LOGGER = Logger.getLogger(FuzzyAnalysisTask.class); 053 private static final int MAX_MEDIA_ITEMS = 10; 054 private Integer _backendId = null; 055 private String _callbackUri = null; 056 private List<FuzzyMedia> _media = null; 057 private Random _random = null; 058 private Long _taskId = null; 059 060 /** 061 * 062 * @param backendId 063 * @param callbackUri 064 * @param media 065 * @param taskId 066 * @throws IllegalArgumentException on bad data 067 */ 068 public FuzzyAnalysisTask(Integer backendId, String callbackUri, List<FuzzyMedia> media, Long taskId) throws IllegalArgumentException { 069 if(taskId == null){ 070 throw new IllegalArgumentException("Invalid "+Definitions.ELEMENT_TASK_ID); 071 } 072 _taskId = taskId; 073 074 if(backendId == null){ 075 throw new IllegalArgumentException("Invalid "+Definitions.ELEMENT_BACKEND_ID+" for task, id : "+_taskId); 076 } 077 _backendId = backendId; 078 if(StringUtils.isBlank(callbackUri)){ 079 throw new IllegalArgumentException("Invalid "+Definitions.ELEMENT_CALLBACK_URI+" : "+callbackUri+" for task, id : "+_taskId); 080 } 081 _callbackUri = callbackUri; 082 083 if(media == null || media.isEmpty()){ 084 throw new IllegalArgumentException("No content for task, id : "+_taskId); 085 } 086 for(FuzzyMedia m : media){ 087 if(!FuzzyMedia.isValid(m)){ 088 throw new IllegalArgumentException("Invalid media, "+Definitions.ELEMENT_GUID+" : "+m.getGUID()+" for task, id : "+_taskId); 089 } 090 } 091 092 _media = new ArrayList<>(media); // preserve the original list 093 _random = new Random(); 094 if(_media.size() > MAX_MEDIA_ITEMS){ // limit the result size to prevent excessive abusing of Google's Translation service 095 media = _media; 096 Collections.shuffle(media, _random); // shuffle to get random items 097 098 _media = new ArrayList<>(MAX_MEDIA_ITEMS); 099 Iterator<FuzzyMedia> iter = media.iterator(); 100 for(int i=0;i<MAX_MEDIA_ITEMS;++i){ 101 _media.add(iter.next()); 102 } 103 } 104 } 105 106 @Override 107 public void run() { 108 List<FuzzyMedia> results = new ArrayList<>(_media.size()); 109 try(FuzzyAnalyzer fa = new FuzzyAnalyzer()){ 110 for(FuzzyMedia m : _media){ 111 Set<String> words = fa.analyze(m.getUrl()); 112 if(words != null){ 113 MediaType mediaType = m.getMediaType(); 114 String guid = m.getGUID(); 115 List<MediaObject> objects = new ArrayList<>(words.size()); 116 for(String word : words){ 117 MediaObject mo = new MediaObject(mediaType, MediaObjectType.KEYWORD); 118 mo.setBackendId(_backendId); 119 mo.setConfirmationStatus(ConfirmationStatus.CANDIDATE); 120 mo.setValue(word); 121 mo.setOwnerUserId(m.getOwnerUserId()); 122 mo.setObjectId(guid+"_"+word); 123 mo.setConfidence(_random.nextInt(100)/100.0); 124 objects.add(mo); 125 } // for 126 127 results.add(new FuzzyMedia(guid, objects, mediaType)); 128 } // if 129 } // for 130 } // try 131 132 TaskResults tr = new TaskResults(_backendId, _taskId, TaskStatus.COMPLETED, TaskType.ANALYSIS); 133 134 if(results.isEmpty()){ 135 LOGGER.debug("No results for task, id : "+_taskId); 136 }else{ 137 tr.setMedia(results); 138 } 139 140 try(CloseableHttpClient client = HttpClients.createDefault()){ 141 HttpPost post = new HttpPost(_callbackUri); 142 FuzzyProperties fp = ServiceInitializer.getPropertyHandler().getSystemProperties(FuzzyProperties.class); 143 String username = fp.getAuthUsername(); 144 if(username != null){ // checking either password or username is OK 145 LOGGER.debug("Using authentication..."); 146 HTTPHeaderUtil.setHTTPBasicAuthHeader(post, username, fp.getAuthPassword()); 147 } 148 149 post.setEntity(new StringEntity(new XMLFormatter().toString(tr))); 150 151 LOGGER.debug("Calling POST "+_callbackUri); 152 LOGGER.debug("Server responded : "+client.execute(post, new BasicResponseHandler())); 153 } catch (IOException ex) { 154 LOGGER.error(ex, ex); 155 } 156 } 157}