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;
017
018import java.util.ArrayList;
019import java.util.Date;
020import java.util.List;
021
022import javax.xml.bind.annotation.XmlAccessType;
023import javax.xml.bind.annotation.XmlAccessorType;
024import javax.xml.bind.annotation.XmlElement;
025import javax.xml.bind.annotation.XmlElementWrapper;
026import javax.xml.bind.annotation.XmlRootElement;
027import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
028
029import org.apache.commons.lang3.StringUtils;
030import org.apache.log4j.Logger;
031
032import service.tut.pori.contentanalysis.CAContentCore.ServiceType;
033
034import com.restfb.types.CategorizedFacebookType;
035import com.restfb.types.NamedFacebookType;
036import com.restfb.types.Photo;
037import com.restfb.types.Photo.Tag;
038import com.restfb.types.Place;
039
040import core.tut.pori.utils.ISODateAdapter;
041
042
043/**
044 * Photo description retrieved from Facebook.
045 * 
046 * <h2>Optional Elements</h2>
047 * <ul>
048 *  <li>{@value service.tut.pori.facebookjazz.Definitions#ELEMENT_COMMENT_LIST}</li>
049 *  <li>{@value service.tut.pori.facebookjazz.Definitions#ELEMENT_LIKE_COUNT}</li>
050 * </ul>
051 * 
052 * <h3>XML Example</h3>
053 * 
054 * {@doc.restlet service="[service.tut.pori.facebookjazz.reference.Definitions#SERVICE_FBJ_REFERENCE_EXAMPLE]" method="[service.tut.pori.facebookjazz.Definitions#ELEMENT_PHOTO_DESCRIPTION]" type="GET" query="" body_uri=""}
055 *
056 * @see com.restfb.types.Photo
057 */
058@XmlRootElement(name=Definitions.ELEMENT_PHOTO_DESCRIPTION)
059@XmlAccessorType(XmlAccessType.NONE)
060public class FacebookPhotoDescription {
061  private static final Logger LOGGER = Logger.getLogger(FacebookPhotoDescription.class);
062  private List<FacebookPhotoTag> _tags = null;
063  private List<FacebookComment> _comments = null;
064  private Integer _descriptionWeight = null;
065  private Photo _photo = null;
066  @XmlElement(name = Definitions.ELEMENT_PHOTO_GUID)
067  private String _photoGUID = null;
068  @XmlElement(name = service.tut.pori.contentanalysis.Definitions.ELEMENT_SERVICE_ID)
069  private ServiceType _serviceType = null;
070  
071  /**
072   * 
073   */
074  public FacebookPhotoDescription(){
075    _photo = new Photo();
076  }
077  
078  /**
079   * 
080   * @param photo
081   * @throws IllegalArgumentException
082   */
083  public FacebookPhotoDescription(Photo photo) throws IllegalArgumentException{
084    if(photo == null){
085      throw new IllegalArgumentException("Invalid photo.");
086    }
087    _photo = photo;
088  }
089
090  /**
091   * 
092   * @return true if this is a valid photo description
093   */
094  public boolean isValid(){
095    if(StringUtils.isBlank(_photo.getName()) && _photo.getComments().isEmpty() && getFacebookLocation() == null){
096      return false;
097    }else{
098      return true;
099    }
100  }
101
102  /**
103   * @see com.restfb.types.Photo#getFrom()
104   * @see com.restfb.types.CategorizedFacebookType#getName()
105   * @see #setFromName(String)
106   * 
107   * @return sender name
108   */
109  @XmlElement(name = Definitions.ELEMENT_MESSAGE_POSTER)
110  public String getFromName() {
111    CategorizedFacebookType from = _photo.getFrom();
112    return (from == null ? null : from.getName());
113  }
114  
115  /**
116   * @param name 
117   * @see com.restfb.types.Photo#setFrom(com.restfb.types.CategorizedFacebookType)
118   * @see #getFromName()
119   */
120  public void setFromName(String name) {
121    if(StringUtils.isBlank(name)){
122      _photo.setFrom(null);
123    }else{
124      CategorizedFacebookType from = _photo.getFrom();
125      if(from == null){
126        from = new CategorizedFacebookType();
127        _photo.setFrom(from);
128      }
129      from.setName(name);
130    }
131  }
132
133  /**
134   * @see com.restfb.types.Photo#getPlace()
135   * @see #setFacebookLocation(FacebookLocation)
136   * 
137   * @return location
138   */
139  @XmlElement(name = Definitions.ELEMENT_LOCATION)
140  public FacebookLocation getFacebookLocation() {
141    return FacebookLocation.getFacebookLocation(_photo.getPlace());
142  }
143  
144  /**
145   * @param location 
146   * @see com.restfb.types.Photo#setPlace(Place)
147   * @see #getFacebookLocation()
148   */
149  public void setFacebookLocation(FacebookLocation location) {
150    _photo.setPlace((location == null ? null : location.toPlace()));
151  }
152
153  /**
154   * @see com.restfb.types.Photo#getCreatedTime()
155   * @see #setCreatedTime(Date)
156   * 
157   * @return created timestamp
158   */
159  @XmlElement(name = Definitions.ELEMENT_CREATED_TIMESTAMP)
160  @XmlJavaTypeAdapter(ISODateAdapter.class)
161  public Date getCreatedTime() {
162    return _photo.getCreatedTime();
163  }
164
165  /**
166   * @see com.restfb.types.Photo#getUpdatedTime()
167   * @see #setUpdatedTime(Date)
168   * 
169   * @return updated timestamp
170   */
171  @XmlElement(name = Definitions.ELEMENT_UPDATED_TIMESTAMP)
172  @XmlJavaTypeAdapter(ISODateAdapter.class)
173  public Date getUpdatedTime() {
174    return _photo.getUpdatedTime();
175  }
176
177  /**
178   * @see com.restfb.types.Photo#getComments()
179   * @see #setDescriptionComments(List)
180   * 
181   * @return comments or null if none
182   */
183  @XmlElementWrapper(name = Definitions.ELEMENT_COMMENT_LIST)
184  @XmlElement(name = Definitions.ELEMENT_COMMENT)
185  public List<FacebookComment> getDescriptionComments() {
186    if(_comments == null){
187      _comments = FacebookComment.getCommentList(_photo.getComments());
188    }
189    return _comments;
190  }
191  
192  /**
193   * 
194   * @param comments
195   * @see #getDescriptionComments()
196   */
197  public void setDescriptionComments(List<FacebookComment> comments) {
198    _comments = comments;
199  }
200
201  /**
202   * @see com.restfb.types.Photo#getLikes()
203   * 
204   * @return like count
205   */
206  @XmlElement(name = Definitions.ELEMENT_LIKE_COUNT)
207  public Long getLikeCount() {
208    return (long) _photo.getLikes().size();  // this is long elsewhere, so make it long here
209  }
210  
211  /**
212   * This method does nothing and exists only to enable unmarshalling/marshalling.
213   * 
214   * If you want to add likes use addLike()
215   * 
216   * @see #addLike(NamedFacebookType)
217   * @see #getLikeCount()
218   * 
219   * @param likeCount
220   */
221  @SuppressWarnings("unused")
222  private void setLikeCount(Long likeCount){
223    LOGGER.warn("Ignored "+Definitions.ELEMENT_LIKE_COUNT+" : "+likeCount);
224  }
225
226  /**
227   * @see com.restfb.types.Photo#getName()
228   * @see #getDescription()
229   * 
230   * @return description
231   */
232  @XmlElement(name = Definitions.ELEMENT_DESCRIPTION)
233  public WeightedStringElement getWDescription() {
234    String description = _photo.getName();
235    if(StringUtils.isBlank(description)){
236      return null;
237    }else{
238      return new WeightedStringElement(description, _descriptionWeight);
239    }
240  }
241  
242  /**
243   * for serialization
244   * 
245   * @param description
246   * @see #setDescription(String)
247   */
248  @SuppressWarnings("unused")
249  private void setWDescription(WeightedStringElement description) {
250    if(description == null){
251      _photo.setName(null);
252      setDescriptionWeight(null);
253    }else{
254      _photo.setName(description.getValue());
255      setDescriptionWeight(description.getWeight());
256    }
257  }
258
259  /**
260   * @see com.restfb.types.Photo#getSource()
261   * 
262   * @return source
263   */
264  @XmlElement(name = Definitions.ELEMENT_SOURCE)
265  public String getSource() {
266    return _photo.getSource();
267  }
268  
269  /**
270   * @see com.restfb.types.Photo#getTags()
271   * @see #setTagList(List)
272   * 
273   * @return tags converted to TagList or null if none
274   */
275  @XmlElementWrapper(name = Definitions.ELEMENT_PHOTO_TAG_LIST)
276  @XmlElement(name = Definitions.ELEMENT_PHOTO_TAG)
277  public List<FacebookPhotoTag> getTagList(){
278    if(_tags != null){
279      return _tags;
280    } 
281    
282    List<Tag> tags = _photo.getTags();
283    if(tags == null || tags.isEmpty()){
284      return null;
285    }
286    _tags = new ArrayList<>();
287    for(Tag t : tags){
288      FacebookPhotoTag tag = FacebookPhotoTag.getFacebookTag(t);
289      if(tag != null){
290        _tags.add(tag);
291      } 
292    } // for
293    if(_tags.isEmpty()){
294      return null;
295    }else{
296      return _tags;
297    }
298  }
299  
300  /**
301   * 
302   * @param tags
303   * @see #getTagList()
304   */
305  public void setTagList(List<FacebookPhotoTag> tags){
306    if(tags == null){
307      _tags = new ArrayList<>(); // clear the tag list
308    }else{ // allow empty
309      _tags = tags;
310    }
311  }
312  
313  /**
314   * 
315   * @param tag
316   * @see #getTagList()
317   */
318  public void addTag(FacebookPhotoTag tag){
319    List<FacebookPhotoTag> tags = getTagList();
320    if(tags == null){
321      tags = new ArrayList<>();
322    }
323    tags.add(tag);
324    _tags = tags; // make sure the updated tag list is the current one
325  }
326
327  /**
328   * @return the descriptionWeight
329   * @see #setDescriptionWeight(Integer)
330   */
331  public Integer getDescriptionWeight() {
332    return _descriptionWeight;
333  }
334
335  /**
336   * @param descriptionWeight the descriptionWeight to set
337   * @see #getDescriptionWeight()
338   */
339  public void setDescriptionWeight(Integer descriptionWeight) {
340    _descriptionWeight = descriptionWeight;
341  }
342
343  /**
344   * @return the photoGUID
345   * @see #setPhotoGUID(String)
346   */
347  public String getPhotoGUID() {
348    return _photoGUID;
349  }
350
351  /**
352   * @param photoGUID the photoGUID to set
353   * @see #getPhotoGUID()
354   */
355  public void setPhotoGUID(String photoGUID) {
356    _photoGUID = photoGUID;
357  }
358
359  /**
360   * @return the serviceType
361   * @see #setServiceType(service.tut.pori.contentanalysis.CAContentCore.ServiceType)
362   */
363  public ServiceType getServiceType() {
364    return _serviceType;
365  }
366
367  /**
368   * @param serviceType the serviceType to set
369   * @see #getServiceType()
370   */
371  public void setServiceType(ServiceType serviceType) {
372    _serviceType = serviceType;
373  }
374
375  /**
376   * @param like
377   * @return true on success
378   * @see com.restfb.types.Photo#addLike(com.restfb.types.NamedFacebookType)
379   * @see #getLikeCount()
380   */
381  public boolean addLike(NamedFacebookType like) {
382    return _photo.addLike(like);
383  }
384
385  /**
386   * @return id
387   * @see com.restfb.types.FacebookType#getId()
388   * @see #setId(String)
389   */
390  public String getId() {
391    return _photo.getId();
392  }
393
394  /**
395   * @param date
396   * @see com.restfb.types.Photo#setCreatedTime(java.util.Date)
397   * @see #getCreatedTime()
398   */
399  public void setCreatedTime(Date date) {
400    _photo.setCreatedTime(date);
401  }
402
403  /**
404   * @param date
405   * @see com.restfb.types.Photo#setUpdatedTime(java.util.Date)
406   * @see #getUpdatedTime()
407   */
408  public void setUpdatedTime(Date date) {
409    _photo.setUpdatedTime(date);
410  }
411
412  /**
413   * @return name
414   * @see com.restfb.types.NamedFacebookType#getName()
415   * @see #setDescription(String)
416   */
417  public String getDescription() {
418    return _photo.getName();
419  }
420
421  /**
422   * @param description
423   * @see com.restfb.types.NamedFacebookType#setName(java.lang.String)
424   * @see #getDescription()
425   */
426  public void setDescription(String description) {
427    _photo.setName(description);
428  }
429  
430  /**
431   * 
432   * @param photos
433   * @return the photos wrapped as descriptions or null if null or empty list was passed
434   */
435  public static List<FacebookPhotoDescription> getFacebookPhotoDescriptions(List<Photo> photos){
436    if(photos == null || photos.isEmpty()){
437      return null;
438    }
439    List<FacebookPhotoDescription> pds = new ArrayList<>(photos.size());
440    for(Photo p : photos){
441      pds.add(new FacebookPhotoDescription(p));
442    }
443    return pds;
444  }
445
446  /**
447   * @param id
448   * @see com.restfb.types.FacebookType#setId(java.lang.String)
449   * @see #getId()
450   */
451  public void setId(String id) {
452    _photo.setId(id);
453  }
454  
455  
456}