package doge;
import doge.photo.DogePhotoManipulator;
import doge.photo.Photo;
import doge.photo.PhotoResource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.gridfs.GridFsTemplate;
import org.springframework.data.mongodb.repository.MongoRepository;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.util.UriComponentsBuilder;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
/**
* Upload new photos using {@code curl -F "file=@/Users/jlong/Desktop/img.jpg" http://joshs-macbook-pro.local:8082/dogifier/1}.
*
* @author Josh Long
* @author Phillip Webb
*/
@Configuration
@ComponentScan
@EnableAutoConfiguration
@EnableEurekaClient
public class DogeApplication {
@Bean
CommandLineRunner init(DogePhotoRepository dogePhotoRepository) {
return a -> dogePhotoRepository.deleteAll();
}
@Bean
@RefreshScope
DogePhotoManipulator dogePhotoManipulator(@Value("${very-so-much-count}") int countOfExclamations, Environment environment) {
DogePhotoManipulator dogePhotoManipulator = new DogePhotoManipulator();
for (int i = 0; i < countOfExclamations; i++) {
String[] e = environment.getProperty("very-so-much-" + (1 + i)).split(" ");
dogePhotoManipulator.addTextOverlay(e[0], e[1], e[2]);
}
return dogePhotoManipulator;
}
public static void main(String[] args) {
SpringApplication.run(DogeApplication.class, args);
}
}
interface DogePhotoRepository extends MongoRepository<DogePhoto, String> {
Collection<DogePhoto> findByKey(String key);
DogePhoto findByKeyAndId(String key, String id);
}
class DogePhoto {
public DogePhoto() {
}
public DogePhoto(String key) {
this.key = key;
}
@Id
private String id;
private String key;
public String getId() {
return id;
}
public String getKey() {
return key;
}
}
@RestController
@RequestMapping(value = "/doges/{key}/photos")
class DogePhotoController {
private final DogePhotoRepository dogePhotoRepository;
private final GridFsTemplate fs;
private final DogePhotoManipulator dogePhotoManipulator;
@RequestMapping(method = RequestMethod.GET)
Collection<DogePhoto> readPhotos(@PathVariable String key) {
return this.dogePhotoRepository.findByKey(key);
}
@RequestMapping(value = "/{id}", method = RequestMethod.GET)
DogePhoto readPhoto(@PathVariable String key, @PathVariable String id) {
return this.dogePhotoRepository.findByKeyAndId(key, id);
}
@RequestMapping(value = "/{id}/photo", method = RequestMethod.GET, produces = MediaType.IMAGE_JPEG_VALUE)
ResponseEntity<PhotoResource> readPhotoResource(@PathVariable String key, @PathVariable String id) {
DogePhoto dogePhoto = this.dogePhotoRepository.findByKeyAndId(key, id);
Photo photo = () -> this.fs.getResource(dogePhoto.getId()).getInputStream();
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.setContentType(MediaType.IMAGE_JPEG);
return new ResponseEntity<>(new PhotoResource(photo), httpHeaders, HttpStatus.OK);
}
@RequestMapping(method = {RequestMethod.POST, RequestMethod.PUT})
ResponseEntity<?> insertPhoto(@PathVariable String key,
@RequestParam MultipartFile file,
UriComponentsBuilder uriBuilder) throws IOException {
Photo photo = this.dogePhotoManipulator.manipulate(file::getInputStream);
DogePhoto dogePhoto = this.dogePhotoRepository.save(new DogePhoto(key));
String id = dogePhoto.getId();
try (InputStream inputStream = photo.getInputStream()) {
this.fs.store(inputStream, id);
}
URI uri = uriBuilder.path("/doges/{key}/photos/{id}/photo").buildAndExpand(key, id).toUri();
Map<String, String> msg = new HashMap<>();
msg.put("uploadDate", java.time.Clock.systemUTC().instant().toString());
msg.put("dogePhotoUri", uri.toString());
msg.put("id", id);
HttpHeaders headers = new HttpHeaders();
headers.setLocation(uri);
return new ResponseEntity<>(msg, headers, HttpStatus.CREATED);
}
@Autowired
public DogePhotoController(
DogePhotoRepository dogePhotoRepository,
GridFsTemplate fs,
DogePhotoManipulator dogePhotoManipulator) {
this.dogePhotoManipulator = dogePhotoManipulator;
this.dogePhotoRepository = dogePhotoRepository;
this.fs = fs;
}
}