package org.springframework.social.flickr.api.impl;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.http.converter.FormHttpMessageConverter;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.social.flickr.api.*;
import org.springframework.social.support.URIBuilder;
import org.springframework.util.Assert;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;
import org.w3c.dom.Element;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.net.URI;
/**
* @author HemantS
* @author Josh Long (josh.long@springsource.com)
*/
public class PhotoTemplate extends AbstractFlickrOperations implements PhotoOperations {
private final RestTemplate restTemplate;
public PhotoTemplate(RestTemplate restTemplate, boolean isAuthorizedForUser,String consumerKey) {
super(isAuthorizedForUser,consumerKey);
this.restTemplate = restTemplate;
}
@Override
public boolean addTags(String photoId, String[] tagList) {
requireAuthorization();
MultiValueMap<String, String> parameters = new LinkedMultiValueMap<String, String>();
parameters.set("photo_id", photoId);
parameters.set("tags", toCommaList(tagList));
restTemplate.postForObject(buildUri("flickr.photos.addTags"), parameters, Object.class);
return true;
}
@Override
public boolean addTags(String photoId, String tags) {
requireAuthorization();
MultiValueMap<String, String> parameters = new LinkedMultiValueMap<String, String>();
parameters.set("photo_id", photoId);
parameters.set("tags", tags);
restTemplate.postForObject(buildUri("flickr.photos.addTags"), parameters, Object.class);
return true;
}
@Override
public boolean removeTag(String tagId) {
requireAuthorization();
MultiValueMap<String, String> parameters = new LinkedMultiValueMap<String, String>();
parameters.set("tag_id", tagId);
restTemplate.postForObject(buildUri("flickr.photos.removeTag"), parameters, Object.class);
return true;
}
@Override
public boolean delete(String photoId) {
requireAuthorization();
MultiValueMap<String, String> parameters = new LinkedMultiValueMap<String, String>();
parameters.set("photo_id", photoId);
restTemplate.postForObject(buildUri("flickr.photos.delete"), parameters, Object.class);
return true;
}
@Override
public Photos getRecent(String perPage, String page, String[] extras) {
MultiValueMap<String, String> parameters = new LinkedMultiValueMap<String, String>();
parameters.set("per_page", perPage);
parameters.set("page", page);
parameters.set("extras", toCommaList(extras));
return restTemplate.getForObject(buildUri("flickr.photos.getRecent", parameters), Photos.class);
}
@Override
public Photo getFavorites(String perPage, String page, String photoId) {
MultiValueMap<String, String> parameters = new LinkedMultiValueMap<String, String>();
parameters.set("per_page", perPage);
parameters.set("page", page);
parameters.set("photo_id", photoId);
return restTemplate.getForObject(buildUri("flickr.photos.getFavorites", parameters), Photo.class);
}
@Override
public PhotoDetail getInfo(String photoId) {
return restTemplate.getForObject(buildUri("flickr.photos.getInfo", "photo_id", photoId), PhotoDetail.class);
}
@Override
public Sizes getSizes(String photoId) {
return restTemplate.getForObject(buildUri("flickr.photos.getSizes", "photo_id", photoId), Sizes.class);
}
@Override
public Perms getPerms(String photoId) {
requireAuthorization();
return restTemplate.getForObject(buildUri("flickr.photos.getPerms", "photo_id", photoId), Perms.class);
}
@Override
public PhotoId setPerms(Perms perms) {
requireAuthorization();
MultiValueMap<String, String> parameters = new LinkedMultiValueMap<String, String>();
parameters.set("photo_id", perms.getId());
if (perms.isIspublic()) {
parameters.set("is_public", "1");
} else {
parameters.set("is_public", "0");
}
if (perms.isIsfamily()) {
parameters.set("is_family", "1");
} else {
parameters.set("is_family", "0");
}
if (perms.isIsfriend()) {
parameters.set("is_friend", "1");
} else {
parameters.set("is_friend", "0");
}
parameters.set("perm_comment", perms.getPermcomment().getPermision());
parameters.set("perm_addmeta", perms.getPermcomment().getPermision());
return restTemplate.postForObject(buildUri("flickr.photos.setPerms"), parameters, PhotoId.class);
}
@Override
public boolean setContentType(String photoId, ContentTypeEnum contentTypeEnum) {
requireAuthorization();
MultiValueMap<String, String> parameters = new LinkedMultiValueMap<String, String>();
parameters.set("photo_id", photoId);
parameters.set("content_type", contentTypeEnum.getType());
restTemplate.postForObject(buildUri("flickr.photos.setContentType"), parameters, Object.class);
return true;
}
@Override
public boolean setSafetyLevel(String photoId, SafetyLevelEnum safetyLevel, Boolean hidden) {
requireAuthorization();
MultiValueMap<String, String> parameters = new LinkedMultiValueMap<String, String>();
parameters.set("photo_id", photoId);
parameters.set("safety_level", safetyLevel.getSafetyLevel());
if (hidden != null) {
if (hidden) {
parameters.set("hidden", "1");
} else {
parameters.set("hidden", "0");
}
}
restTemplate.postForObject(buildUri("flickr.photos.setSafetyLevel"), parameters, Object.class);
return true;
}
@Override
public boolean setSafetyLevel(String photoId, SafetyLevelEnum safetyLevel) {
return setSafetyLevel(photoId, safetyLevel, null);
}
@Override
public boolean setMeta(String photoId, String title, String description) {
requireAuthorization();
MultiValueMap<String, String> parameters = new LinkedMultiValueMap<String, String>();
parameters.set("photo_id", photoId);
if (StringUtils.hasText(title))
parameters.set("title", title);
if (StringUtils.hasText(description))
parameters.set("description", description);
restTemplate.postForObject(buildUri("flickr.photos.setMeta"), parameters, Object.class);
return true;
}
@Override
public PhotoId rotate(String photoId, RotateEnum rotation) {
requireAuthorization();
MultiValueMap<String, String> parameters = new LinkedMultiValueMap<String, String>();
parameters.set("photo_id", photoId);
parameters.set("degrees", rotation.getRotation());
return restTemplate.postForObject(buildUri("flickr.photos.transform.rotate"), parameters, PhotoId.class);
}
private String toCommaList(String[] a) {
if (a == null)
return "null";
int iMax = a.length - 1;
if (iMax == -1)
return "";
StringBuilder b = new StringBuilder();
for (int i = 0; ; i++) {
b.append(a[i]);
if (i == iMax)
return b.toString();
b.append(",");
}
}
protected void ensureSupportsFormHttpUploads() {
boolean hasFormHttpMessageConverter = false;
for (HttpMessageConverter mc : restTemplate.getMessageConverters()) {
if (mc instanceof FormHttpMessageConverter) {
hasFormHttpMessageConverter = true;
break;
}
}
if (!hasFormHttpMessageConverter) {
this.restTemplate.getMessageConverters().add(new FormHttpMessageConverter()); // just in case
}
}
/**
* handles setting other properties on the photo after the post, since, atm,
* i can't figure out how to POST the data correctly.
*/
protected void setPropertiesOnPhoto(String photoId, String title, String description, String[] tags, Perms perms, ContentTypeEnum contentType, HiddenEnum hiddenType) {
if (hiddenType != null) {
System.out.println("NB: this API does not yet support setting the HiddenEnum on a Photo");
}
setMeta(photoId, title, description);
if (null != tags) {
addTags(photoId, tags);
}
if (null != perms) {
setPerms(perms);
}
if (null != contentType) {
setContentType(photoId, contentType);
}
}
@Override
public String upload(File photo, String title, String description, String[] tags, Perms perms, ContentTypeEnum contentType, HiddenEnum hiddenType) {
Resource res = new FileSystemResource(photo);
requireAuthorization();
ensureSupportsFormHttpUploads();
try {
Assert.notNull(res);
Assert.isTrue(res.exists());
MultiValueMap<String, Object> parms = new LinkedMultiValueMap<String, Object>();
parms.set("photo", res);
URI uri = URIBuilder.fromUri("http://api.flickr.com/services/upload/").build();
String response = restTemplate.postForObject(uri, parms, String.class);
Element node = DocumentBuilderFactory
.newInstance()
.newDocumentBuilder()
.parse(new ByteArrayInputStream(response.getBytes()))
.getDocumentElement();
String id = (node.getElementsByTagName("photoid").item(0).getTextContent());
setPropertiesOnPhoto(id, title, description, tags, perms, contentType, hiddenType);
return id;
} catch (Throwable thr) {
throw new RuntimeException(thr);
}
}
}