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.twitterjazz.reference;
017
018import java.util.ArrayList;
019import java.util.Date;
020import java.util.EnumSet;
021import java.util.List;
022import java.util.Random;
023import java.util.UUID;
024
025import org.apache.commons.lang3.RandomStringUtils;
026
027import service.tut.pori.contentanalysis.AsyncTask.TaskType;
028import service.tut.pori.contentanalysis.CAContentCore.ServiceType;
029import service.tut.pori.contentanalysis.PhotoList;
030import service.tut.pori.contentanalysis.MediaObject;
031import service.tut.pori.contentanalysis.MediaObjectList;
032import service.tut.pori.contentanalysis.reference.CAXMLObjectCreator;
033import service.tut.pori.contentstorage.TwitterPhotoStorage;
034import service.tut.pori.twitterjazz.TwitterExtractor.ContentType;
035import service.tut.pori.twitterjazz.TwitterLocation;
036import service.tut.pori.twitterjazz.TwitterPhotoDescription;
037import service.tut.pori.twitterjazz.TwitterPhotoTag;
038import service.tut.pori.twitterjazz.TwitterProfile;
039import service.tut.pori.twitterjazz.TwitterStatusMessage;
040import service.tut.pori.twitterjazz.TwitterSummarizationTaskDetails;
041import service.tut.pori.twitterjazz.TwitterTaskResponse;
042import service.tut.pori.twitterjazz.TwitterUserDetails;
043import service.tut.pori.twitterjazz.TwitterVideoDescription;
044import core.tut.pori.context.ServiceInitializer;
045import core.tut.pori.http.parameters.DataGroups;
046import core.tut.pori.http.parameters.Limits;
047import core.tut.pori.users.UserIdentity;
048
049/**
050 * 
051 * class that can be used to created example objects/object lists
052 * 
053 */
054public class TJXMLObjectCreator {
055  private static final int TEXT_LENGTH = 64;
056  private static int TWITTER_CHARACTER_LIMIT = 140;
057  private static int WORD_MIN_LENGTH = 3;
058  private static int WORD_MAX_LENGTH = 10;
059  private CAXMLObjectCreator _CACreator = null;
060  
061  /**
062   * 
063   * @param seed for random generator, or null to use default (system time in nanoseconds)
064   */
065  public TJXMLObjectCreator(Long seed){
066    _CACreator = new CAXMLObjectCreator(seed);
067  }
068
069  /**
070   * @return the seed
071   */
072  public long getSeed() {
073    return _CACreator.getSeed();
074  }
075
076  /**
077   * @see service.tut.pori.contentanalysis.reference.CAXMLObjectCreator#createBackendId()
078   * 
079   * @return randomly generated back-end id
080   */
081  public Integer createBackendId() {
082    return _CACreator.createBackendId();
083  }
084  
085  /**
086   * 
087   * @param dataGroups 
088   * @param limits
089   * @param taskId if null, generated randomly
090   * @param taskType  if null, generated randomly
091   * @return randomly generated task response
092   */
093  public TwitterTaskResponse createTwitterTaskResponse(DataGroups dataGroups, Limits limits, Long taskId, TaskType taskType) {
094    TwitterTaskResponse r = new TwitterTaskResponse();
095    Random random = _CACreator.getRandom();
096    r.setTaskId((taskId == null ? Math.abs(random.nextLong()) : taskId));
097    Integer backendId = Math.abs(random.nextInt());
098    r.setBackendId(backendId);
099    r.setMessage(RandomStringUtils.randomAlphabetic(TEXT_LENGTH));
100    r.setTaskType((taskType == null ? _CACreator.createTaskType() : taskType));
101    r.setStatus(_CACreator.createTaskStatus());
102    PhotoList photoList = _CACreator.createPhotoList(null, dataGroups, limits, null, _CACreator.createUserIdentity());
103    if(!PhotoList.isEmpty(photoList)){
104      for(service.tut.pori.contentanalysis.Photo p : photoList.getPhotos()){ // make sure all media objects have the same back-end id as the task has, and that service types match
105        MediaObjectList mediaObjectList = p.getMediaObjects();
106        p.setServiceType(ServiceType.FACEBOOK_PHOTO);
107        if(!MediaObjectList.isEmpty(mediaObjectList)){
108          for(MediaObject vo : mediaObjectList.getMediaObjects()){
109            vo.setBackendId(backendId);
110            vo.setServiceType(ServiceType.FACEBOOK_JAZZ);
111          }
112        }
113      }
114      r.setPhotoList(photoList);
115    }
116    MediaObjectList mediaObjectList = _CACreator.createMediaObjectList(null, dataGroups, limits, EnumSet.of(ServiceType.FACEBOOK_JAZZ));
117    if(!MediaObjectList.isEmpty(mediaObjectList)){
118      for(MediaObject vo : mediaObjectList.getMediaObjects()){ // make sure all media objects have the same back-end id as the task has
119        vo.setBackendId(backendId);
120      }
121      r.setMediaObjects(mediaObjectList);
122    }
123    return r;
124  }
125  
126  /**
127   * 
128   * @param photoDescriptionCount
129   * @param statusMessageCount
130   * @param videoDescriptionCount
131   * @param tagCount 
132   * @return randomly generated profile
133   */
134  public TwitterProfile createTwitterProfile(int photoDescriptionCount, int statusMessageCount, int videoDescriptionCount, int tagCount){
135    TwitterProfile profile = new TwitterProfile(createTwitterUserDetails());
136    
137    if(photoDescriptionCount > 0){
138      List<TwitterPhotoDescription> descriptions = new ArrayList<>(photoDescriptionCount);
139      for(int i=0;i<photoDescriptionCount;++i){
140        descriptions.add(createTwitterPhotoDescription(tagCount));
141      }
142      profile.setPhotoDescriptions(descriptions);
143    }
144    
145    if(videoDescriptionCount > 0){
146      List<TwitterVideoDescription> descriptions = new ArrayList<>(videoDescriptionCount);
147      for(int i=0;i<videoDescriptionCount;++i){
148        descriptions.add(createTwitterVideoDescription());
149      }
150      profile.setVideoDescriptions(descriptions);
151    }
152    
153    if(statusMessageCount > 0){
154      List<TwitterStatusMessage> statuses = new ArrayList<>(statusMessageCount);
155      for(int i=0;i<statusMessageCount;++i){
156        statuses.add(createTwitterStatusMessage());
157      }
158      profile.setStatusMessages(statuses);
159    }
160    
161    return profile;
162  }
163  
164  /**
165   * 
166   * @return randomly generated details
167   */
168  public TwitterUserDetails createTwitterUserDetails(){
169    TwitterUserDetails tud = new TwitterUserDetails();
170    tud.setBio(RandomStringUtils.randomAlphabetic(TEXT_LENGTH));
171    Random r = _CACreator.getRandom();
172    tud.setFavoritesCount(Math.abs(r.nextInt()));
173    tud.setFriendsCount(Math.abs(r.nextInt()));
174    tud.setFollowersCount(Math.abs(r.nextInt()));
175    tud.setName(RandomStringUtils.randomAlphabetic(TEXT_LENGTH));
176    tud.setScreenName(RandomStringUtils.randomAlphabetic(TEXT_LENGTH));
177    tud.setTwitterId(String.valueOf(Math.abs(r.nextLong())));
178    tud.setLocation(createTwitterLocation());
179    tud.setProtected(r.nextBoolean());
180    tud.setUserId(_CACreator.createUserIdentity());
181    return tud;
182  }
183  
184  /**
185   * 
186   * @return randomly generated video description
187   */
188  public TwitterVideoDescription createTwitterVideoDescription(){
189    TwitterVideoDescription d = new TwitterVideoDescription();
190    d.setCreatedTime(CAXMLObjectCreator.createRandomDate(new Date(), _CACreator.getRandom()));
191    d.setLocation(createTwitterLocation());
192    d.setDescription(createStatusMessageText());
193    d.setFromScreenName(RandomStringUtils.randomAlphabetic(TEXT_LENGTH));
194    return d;
195  }
196  
197  /**
198   * 
199   * @param tagCount 
200   * @return randomly generated photo description
201   */
202  public TwitterPhotoDescription createTwitterPhotoDescription(int tagCount){
203    TwitterPhotoDescription tp = new TwitterPhotoDescription();
204    Random r = _CACreator.getRandom();
205    tp.setCreatedTime(CAXMLObjectCreator.createRandomDate(new Date(),r));
206    tp.setDescription(createStatusMessageText());
207    tp.setFromName(RandomStringUtils.randomAlphabetic(TEXT_LENGTH));
208    tp.setLocation(createTwitterLocation());
209    tp.setEntityUrl(createRandomSecureUrl());
210    tp.setEntityId(String.valueOf(Math.abs(r.nextLong())));
211    tp.setPhotoGUID(UUID.randomUUID().toString());
212    tp.setServiceType(TwitterPhotoStorage.SERVICE_TYPE);
213    for(int i=0;i<tagCount;++i){
214      tp.addTag(createTwitterPhotoTag());
215    }
216    return tp;
217  }
218  
219  /**
220   * 
221   * @return randomly generated location
222   */
223  public TwitterLocation createTwitterLocation(){
224    TwitterLocation location = new TwitterLocation();
225    location.setName(RandomStringUtils.randomAlphabetic(TEXT_LENGTH));
226    Random r = _CACreator.getRandom();
227    location.setLatitude((double) (r.nextInt(180)-90));
228    location.setLongitude((double) (r.nextInt(360)-180));
229    return location;
230  }
231  
232  /**
233   * 
234   * @return randomly generated tag
235   */
236  public TwitterPhotoTag createTwitterPhotoTag(){
237    TwitterPhotoTag tag = new TwitterPhotoTag();
238    tag.setServiceType(TwitterPhotoStorage.SERVICE_TYPE);
239    tag.setValue(RandomStringUtils.randomAlphabetic(TEXT_LENGTH));
240    return tag;
241  }
242  
243  /**
244   * 
245   * @return randomly generated status message
246   */
247  public TwitterStatusMessage createTwitterStatusMessage(){
248    TwitterStatusMessage message = new TwitterStatusMessage();
249    message.setFromName(RandomStringUtils.randomAlphabetic(TEXT_LENGTH));
250    message.setMessage(createStatusMessageText());
251    message.setUpdatedTime(CAXMLObjectCreator.createRandomDate(new Date(), _CACreator.getRandom()));
252    return message;
253  }
254  
255  /**
256   * 
257   * @return randomly generated URL with SSL-prefix (HTTPS)
258   */
259  public static String createRandomSecureUrl(){
260    return CAXMLObjectCreator.createRandomUrl().replace("http://", "https://");
261  }
262  
263  /**
264   * 
265   * @param photoDescriptionCount
266   * @param statusMessageCount
267   * @param videoDescriptionCount
268   * @param tagCount 
269   * @return randomly generated task details
270   */
271  public TwitterSummarizationTaskDetails createTwitterSummarizationTaskDetails(int photoDescriptionCount, int statusMessageCount, int videoDescriptionCount, int tagCount) {
272    TwitterSummarizationTaskDetails details = new TwitterSummarizationTaskDetails();
273    Random r = _CACreator.getRandom();
274    _CACreator.populateAbstractTaskDetails(Math.abs(r.nextInt()), details, Math.abs(r.nextLong()), TaskType.TWITTER_PROFILE_SUMMARIZATION);
275    details.setProfile(createTwitterProfile(photoDescriptionCount, videoDescriptionCount, statusMessageCount, tagCount));
276    details.setContentTypes(EnumSet.allOf(ContentType.class));
277    details.setCallbackUri(generateFinishedCallbackUri()); // override the default uri
278    return details;
279  }
280  
281  /**
282   * 
283   * @return the default task finished callback uri
284   */
285  public String generateFinishedCallbackUri(){
286    return ServiceInitializer.getPropertyHandler().getRESTBindContext()+service.tut.pori.twitterjazz.reference.Definitions.SERVICE_TJ_REFERENCE_SERVER+"/"+service.tut.pori.contentanalysis.Definitions.METHOD_TASK_FINISHED;
287  }
288  
289  /**
290   * 
291   * @return randomly generated text
292   */
293  public String createStatusMessageText(){
294    StringBuilder text = new StringBuilder(TWITTER_CHARACTER_LIMIT);
295    for(int length=0;length<TWITTER_CHARACTER_LIMIT;length=text.length()){
296      String word = createRandomWord();
297      if(_CACreator.getRandom().nextBoolean()){ // make occasionally a hashtag
298        if(word.length()+length+1 < TWITTER_CHARACTER_LIMIT){
299          text.append("#");
300          text.append(word);
301        }else{ // no more room for a hashtag
302          break;
303        }
304      }else if(word.length()+length < TWITTER_CHARACTER_LIMIT){
305        text.append(word);
306      }else{ // no more room for a word
307        break;
308      }
309      text.append(' ');
310    }
311    return text.toString().trim();
312  }
313  
314  /**
315   * 
316   * @return randomly generated word
317   */
318  private String createRandomWord(){
319    return RandomStringUtils.randomAlphanumeric(_CACreator.getRandom().nextInt(WORD_MAX_LENGTH-WORD_MIN_LENGTH)+WORD_MIN_LENGTH);
320  }
321  
322  /**
323   * 
324   * @param backendId
325   * @param dataGroups
326   * @param limits
327   * @param userId
328   * @return randomly generated tag list
329   */
330  public MediaObjectList createTagList(Integer backendId, DataGroups dataGroups, Limits limits, UserIdentity userId) {
331    MediaObjectList objects = _CACreator.createMediaObjectList(null, dataGroups, limits, EnumSet.of(ServiceType.TWITTER_JAZZ));
332    if(!MediaObjectList.isEmpty(objects)){  
333      userId = UserIdentity.isValid(userId) ? userId : _CACreator.createUserIdentity();
334      backendId = createBackendId();
335      for(MediaObject o : objects.getMediaObjects()){
336        o.setOwnerUserId(userId);
337        o.setBackendId(backendId);
338      }
339    }
340    return objects;
341  }
342}