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.Arrays;
020import java.util.Date;
021import java.util.List;
022
023import javax.xml.bind.annotation.XmlAccessType;
024import javax.xml.bind.annotation.XmlAccessorType;
025import javax.xml.bind.annotation.XmlElement;
026import javax.xml.bind.annotation.XmlElementWrapper;
027import javax.xml.bind.annotation.XmlRootElement;
028import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
029
030import org.apache.commons.lang3.ArrayUtils;
031import org.apache.commons.lang3.StringUtils;
032import org.apache.commons.lang3.time.FastDateFormat;
033
034import com.restfb.types.NamedFacebookType;
035import com.restfb.types.User;
036import com.restfb.util.DateUtils;
037
038import core.tut.pori.users.UserIdentity;
039import core.tut.pori.utils.ISODateAdapter;
040
041/**
042 * output class for facebook user details.
043 * 
044 * <h2>Optional Elements</h2>
045 * <ul>
046 *  <li>{@value service.tut.pori.facebookjazz.Definitions#ELEMENT_BIO}</li>
047 *  <li>{@value service.tut.pori.facebookjazz.Definitions#ELEMENT_BIRTHDAY}</li>
048 *  <li>{@value service.tut.pori.facebookjazz.Definitions#ELEMENT_GENDER}</li>
049 *  <li>{@value service.tut.pori.facebookjazz.Definitions#ELEMENT_HOMETOWN}</li>
050 *  <li>{@value service.tut.pori.facebookjazz.Definitions#ELEMENT_LOCATION}</li>
051 *  <li>{@value service.tut.pori.facebookjazz.Definitions#ELEMENT_POLITICAL}</li>
052 *  <li>{@value service.tut.pori.facebookjazz.Definitions#ELEMENT_RELATIONSHIP_LIST}</li>
053 *  <li>{@value service.tut.pori.facebookjazz.Definitions#ELEMENT_RELIGION}</li>
054 * </ul>
055 * 
056 * <h3>XML Example</h3>
057 * 
058 * {@doc.restlet service="[service.tut.pori.facebookjazz.reference.Definitions#SERVICE_FBJ_REFERENCE_EXAMPLE]" method="[service.tut.pori.facebookjazz.Definitions#ELEMENT_USER_DETAILS]" type="GET" query="" body_uri=""}
059 *
060 * @see com.restfb.types.User
061 */
062@XmlRootElement(name=Definitions.ELEMENT_USER_DETAILS)
063@XmlAccessorType(XmlAccessType.NONE)
064public class FacebookUserDetails {
065  private static final FastDateFormat RESTFB_FB_SHORT = FastDateFormat.getInstance(DateUtils.FACEBOOK_SHORT_DATE_FORMAT);
066  private static final String SEPARATOR_LASTNAME_FIRSTNAME = ",";
067  private static final String SEPARATOR_FIRSTNAME_MIDDLENAME = " ";
068  private User _user = null;
069  private UserIdentity _userId = null;
070  
071  /**
072   * 
073   */
074  public FacebookUserDetails() {
075    _user = new User();
076  }
077  
078  /**
079   * 
080   * @param user
081   * @throws IllegalArgumentException 
082   */
083  public FacebookUserDetails(User user) throws IllegalArgumentException{
084    if(user == null){
085      throw new IllegalArgumentException("Invalid user.");
086    }
087    _user = user;
088  }
089
090  /**
091   * @see com.restfb.types.User#getBio()
092   * @see #setBio(String)
093   * 
094   * @return user's bio
095   */
096  @XmlElement(name = Definitions.ELEMENT_BIO)
097  public String getBio() {
098    return _user.getBio();
099  }
100
101  /**
102   * @see com.restfb.types.User#getFirstName()
103   * @see com.restfb.types.User#getMiddleName()
104   * @see com.restfb.types.User#getLastName()
105   * 
106   * @return full name of the user in format: LASTNAME, FIRSTNAME MIDDLENAME
107   */
108  @XmlElement(name = Definitions.ELEMENT_NAME)
109  public String getFullName() {
110    StringBuilder name = new StringBuilder(_user.getLastName());
111    name.append(SEPARATOR_LASTNAME_FIRSTNAME);
112    name.append(' ');
113    name.append(_user.getFirstName());
114    String middleName = _user.getMiddleName();
115    if(!StringUtils.isBlank(middleName)){
116      name.append(SEPARATOR_FIRSTNAME_MIDDLENAME);
117      name.append(middleName);
118    }
119    return name.toString();
120  }
121  
122  /**
123   * For serialization
124   * 
125   * @see com.restfb.types.User#setFirstName(String)
126   * @see com.restfb.types.User#setMiddleName(String)
127   * @see com.restfb.types.User#setLastName(String)
128   * 
129   * @param name full name of the user in format: LASTNAME, FIRSTNAME MIDDLENAME where MIDDLENAME is optional
130   * @throws IllegalArgumentException
131   */
132  @SuppressWarnings("unused")
133  private void setFullName(String name) throws IllegalArgumentException{
134    String firstname = null;
135    String middlename = null;
136    String lastname = null;
137    String[] parts = StringUtils.split(name, SEPARATOR_LASTNAME_FIRSTNAME);
138    if(!ArrayUtils.isEmpty(parts)){
139      lastname = parts[0].trim();
140      if(parts.length == 2){
141        parts = StringUtils.split(parts[1].trim(), SEPARATOR_FIRSTNAME_MIDDLENAME, 1); // split once so that multiple names will be split to a single firstname and the rest will be as "middle name"
142        firstname = parts[0].trim();
143        if(parts.length > 1){
144          middlename = parts[1].trim();
145        }
146      }else{
147        throw new IllegalArgumentException("Invalid fullname: "+name);
148      }
149    }
150    _user.setFirstName(firstname);
151    _user.setMiddleName(middlename);
152    _user.setLastName(lastname);
153  }
154
155  /**
156   * @see com.restfb.types.User#getUpdatedTime()
157   * @see #setUpdatedTime(Date)
158   * 
159   * @return updated timestamp
160   */
161  @XmlJavaTypeAdapter(ISODateAdapter.class)
162  @XmlElement(name = Definitions.ELEMENT_UPDATED_TIMESTAMP)
163  public Date getUpdatedTime() {
164    return _user.getUpdatedTime();
165  }
166
167  /**
168   * @see com.restfb.types.User#getBirthdayAsDate()
169   * @see #setBirthdayAsDate(Date)
170   * 
171   * @return birthday
172   */
173  @XmlJavaTypeAdapter(ISODateAdapter.class)
174  @XmlElement(name = Definitions.ELEMENT_BIRTHDAY)
175  public Date getBirthdayAsDate() {
176    return _user.getBirthdayAsDate();
177  }
178
179  /**
180   * @see com.restfb.types.User#getGender()
181   * @see #setGender(String)
182   * 
183   * @return gender
184   */
185  @XmlElement(name = Definitions.ELEMENT_GENDER)
186  public String getGender() {
187    String gender = _user.getGender();
188    if(gender != null){
189      gender = gender.toUpperCase();   // make sure it is always upper case
190    }
191    return gender;
192  }
193
194  /**
195   * 
196   * @return list of relationships or null if none
197   */
198  @XmlElementWrapper(name = Definitions.ELEMENT_RELATIONSHIP_LIST)
199  @XmlElement(name = Definitions.ELEMENT_RELATIONSHIP)
200  public List<FacebookRelationship> getRelationShip() {
201    FacebookRelationship r = FacebookRelationship.getFacebookRelationShip(_user);
202    if(r == null){
203      return null;
204    }else{
205      return new ArrayList<>(Arrays.asList(r));
206    }
207  }
208  
209  /**
210   * for serialization
211   * 
212   * @param relations currently only a single relationship is supported
213   * @throws IllegalArgumentException
214   */
215  @SuppressWarnings("unused")
216  private void setRelationShip(List<FacebookRelationship> relations) throws IllegalArgumentException{
217    if(relations == null || relations.isEmpty()){
218      new FacebookRelationship().toUser(_user);
219    }else if(relations.size() > 1){
220      throw new IllegalArgumentException("Only a single relationship is supported.");
221    }else{
222      relations.get(0).toUser(_user);
223    }
224  }
225
226  /**
227   * @see com.restfb.types.User#getHometownName()
228   * @see #setHometownName(String)
229   * 
230   * @return hometown
231   */
232  @XmlElement(name = Definitions.ELEMENT_HOMETOWN)
233  public String getHometownName() {
234    return _user.getHometownName();
235  }
236  
237  /**
238   * @param name
239   * @see com.restfb.types.User#setHometown(com.restfb.types.NamedFacebookType)
240   * @see #getHometownName()
241   */
242  public void setHometownName(String name) {
243    NamedFacebookType hometown = new NamedFacebookType();
244    hometown.setName(name);
245    _user.setHometown(hometown);
246  }
247
248  /**
249   * @see com.restfb.types.User#getLocation()
250   * @see #setFacebookLocation(FacebookLocation)
251   * 
252   * @return location
253   */
254  @XmlElement(name = Definitions.ELEMENT_LOCATION)
255  public FacebookLocation getFacebookLocation() {
256    return FacebookLocation.getFacebookLocation(_user.getLocation());
257  }
258  
259  /**
260   * @see com.restfb.types.User#setLocation(NamedFacebookType)
261   * @see #getFacebookLocation()
262   * 
263   * @param location
264   */
265  public void setFacebookLocation(FacebookLocation location) {
266    _user.setLocation((location == null ? null : location.toNamedFacebookType()));
267  }
268
269  /**
270   * @see com.restfb.types.User#getPolitical()
271   * @see #setPolitical(String)
272   * 
273   * @return political
274   */
275  @XmlElement(name = Definitions.ELEMENT_POLITICAL)
276  public String getPolitical() {
277    return _user.getPolitical();
278  }
279
280  /**
281   * @see com.restfb.types.User#getReligion()
282   * @see #setReligion(String)
283   * 
284   * @return religion
285   */
286  @XmlElement(name = Definitions.ELEMENT_RELIGION)
287  public String getReligion() {
288    return _user.getReligion();
289  }
290
291  /**
292   * @see #getUserId()
293   * 
294   * @return user identity value
295   */
296  @XmlElement(name = core.tut.pori.users.Definitions.ELEMENT_USER_ID)
297  public Long getUserIdValue(){
298    return (_userId == null ? null : _userId.getUserId());
299  }
300  
301  /**
302   * for serialization
303   * 
304   * @param value 
305   * @see #setUserId(UserIdentity)
306   */
307  @SuppressWarnings("unused")
308  private void setUserIdValue(Long value){
309    setUserId((value == null ? null : new UserIdentity(value)));
310  }
311
312  /**
313   * 
314   * @return user identity
315   * @see #setUserId(UserIdentity)
316   */
317  public UserIdentity getUserId() {
318    return _userId;
319  }
320
321  /**
322   * 
323   * @param userId
324   * @see #getUserId()
325   */
326  public void setUserId(UserIdentity userId) {
327    _userId = userId;
328  }
329
330  /**
331   * @see com.restfb.types.User#getId()
332   * @see #setId(String)
333   * 
334   * @return facebook user id
335   */
336  @XmlElement(name = Definitions.ELEMENT_FACEBOOK_ID)
337  public String getId() {
338    return _user.getId();
339  }
340
341  /**
342   * @param id
343   * @see com.restfb.types.FacebookType#setId(java.lang.String)
344   * @see #getId()
345   */
346  public void setId(String id) {
347    _user.setId(id);
348  }
349
350  /**
351   * @param bio
352   * @see com.restfb.types.User#setBio(java.lang.String)
353   * @see #getBio()
354   */
355  public void setBio(String bio) {
356    _user.setBio(bio);
357  }
358
359  /**
360   * @param birthday
361   * @see com.restfb.types.User#setBirthday(java.lang.String)
362   * @see #getBirthdayAsDate()
363   */
364  public void setBirthdayAsDate(Date birthday) {
365    _user.setBirthday(toRestFBShortDateString(birthday));
366  }
367
368  /**
369   * @param name
370   * @see com.restfb.types.User#setFirstName(java.lang.String)
371   */
372  public void setFirstName(String name) {
373    _user.setFirstName(name);
374  }
375
376  /**
377   * @param gender
378   * @see com.restfb.types.User#setGender(java.lang.String)
379   * @see #getGender()
380   */
381  public void setGender(String gender) {
382    _user.setGender(gender);
383  }
384
385  /**
386   * @param name
387   * @see com.restfb.types.User#setLastName(java.lang.String)
388   */
389  public void setLastName(String name) {
390    _user.setLastName(name);
391  }
392
393  /**
394   * @param name
395   * @see com.restfb.types.User#setMiddleName(java.lang.String)
396   */
397  public void setMiddleName(String name) {
398    _user.setMiddleName(name);
399  }
400
401  /**
402   * @param political
403   * @see com.restfb.types.User#setPolitical(java.lang.String)
404   * @see #getPolitical()
405   */
406  public void setPolitical(String political) {
407    _user.setPolitical(political);
408  }
409
410  /**
411   * @param status
412   * @see com.restfb.types.User#setRelationshipStatus(java.lang.String)
413   * @see #getRelationShip()
414   */
415  public void setRelationshipStatus(String status) {
416    _user.setRelationshipStatus(status);
417  }
418
419  /**
420   * @param religion
421   * @see com.restfb.types.User#setReligion(java.lang.String)
422   * @see #getReligion()
423   */
424  public void setReligion(String religion) {
425    _user.setReligion(religion);
426  }
427
428  /**
429   * @param sOther
430   * @see com.restfb.types.User#setSignificantOther(com.restfb.types.NamedFacebookType)
431   * @see #getRelationShip()
432   */
433  public void setSignificantOther(NamedFacebookType sOther) {
434    _user.setSignificantOther(sOther);
435  }
436
437  /**
438   * @param date
439   * @see com.restfb.types.User#setUpdatedTime(java.util.Date)
440   * @see #getUpdatedTime()
441   */
442  public void setUpdatedTime(Date date) {
443    _user.setUpdatedTime(date);
444  }
445
446  /**
447   * @return facebook user name
448   * @see com.restfb.types.NamedFacebookType#getName()
449   */
450  public String getName() {
451    return _user.getName();
452  }
453  
454  /**
455   * 
456   * @param date
457   * @return the given date converted to string in RestFB short format or null if null was passed
458   */
459  public static String toRestFBShortDateString(Date date){
460    if(date == null){
461      return null;
462    }
463    synchronized (RESTFB_FB_SHORT) {
464      return RESTFB_FB_SHORT.format(date);
465    }
466  }
467}