package com.momega.spacesimulator.server.controller; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.io.ByteArrayResource; 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.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; import com.momega.spacesimulator.model.CelestialBody; import com.momega.spacesimulator.model.HistoryPoint; import com.momega.spacesimulator.model.Model; import com.momega.spacesimulator.model.MovingObject; import com.momega.spacesimulator.model.Spacecraft; import com.momega.spacesimulator.model.Timestamp; import com.momega.spacesimulator.server.data.Collection; import com.momega.spacesimulator.server.data.ModelExecutor; import com.momega.spacesimulator.server.data.ModelRunnable; import com.momega.spacesimulator.service.ModelSerializer; @RestController @RequestMapping("/model") public class ModelController { private static final Logger logger = LoggerFactory.getLogger(ModelController.class); @Autowired private Collection<Model> modelCollection; @Autowired private ModelExecutor modelExecutor; @Autowired private ModelSerializer modelSerializer; @RequestMapping(value = "/get/{id}", method = RequestMethod.GET) public Model get(@PathVariable("id") String id) { logger.info("get id = {}", id); ModelRunnable runnable = modelExecutor.get(id); return getModelSnapshot(id, runnable); } @RequestMapping(value = "/download/{id}", method = RequestMethod.GET) public ResponseEntity<ByteArrayResource> download(@PathVariable("id") String id) throws IOException { logger.info("get id = {}", id); ModelRunnable runnable = modelExecutor.get(id); Model m = getModelSnapshot(id, runnable); byte[] bytes = modelSerializer.toBytes(m); ByteArrayResource resource = new ByteArrayResource(bytes); HttpHeaders respHeaders = new HttpHeaders(); respHeaders.setContentType(new MediaType("application", "json")); respHeaders.setContentLength(resource.contentLength()); respHeaders.setContentDispositionFormData("attachment", m.getName() + ".json"); ResponseEntity<ByteArrayResource> result = new ResponseEntity<ByteArrayResource>(resource, respHeaders, HttpStatus.OK); return result; } @RequestMapping(value = "/list", method = RequestMethod.GET) public List<Project> list() { List<Project> result = new ArrayList<>(); for(Map.Entry<String, Model> entry : modelCollection.getAll().entrySet()) { String id = entry.getKey(); Model model = entry.getValue(); Project p = toProject(id, model); result.add(p); } return result; } @RequestMapping(value = "/stop/{id}", method = RequestMethod.GET) public String stop(@PathVariable("id") String id) { modelExecutor.stop(id); return id; } @RequestMapping(value = "/resume/{id}", method = RequestMethod.GET) public String resume(@PathVariable("id") String id) { Model model = modelCollection.get(id); modelCollection.update(id, model); modelExecutor.create(model, id); return id; } @RequestMapping(value = "/close/{id}", method = RequestMethod.GET) public String close(@PathVariable("id") String id) { logger.info("closing id = {}", id); stop(id); modelCollection.remove(id); return id; } @RequestMapping(value = "/item/{id}", method = RequestMethod.GET) public Project getProject(@PathVariable("id") String id) { logger.info("get project, id = {}", id); Model model = modelCollection.get(id); Project p = toProject(id, model); return p; } @RequestMapping(value = "/time/{id}", method = RequestMethod.GET) public Timestamp getTime(@PathVariable("id") String id) { logger.info("get time, id = {}", id); ModelRunnable runnable = modelExecutor.get(id); return runnable.getModel().getTime(); } @RequestMapping(value = "/snapshot/{id}", method = RequestMethod.GET) public String takeSnapshot(@PathVariable("id") String id) { logger.info("create builder, id = {}", id); ModelRunnable runnable = modelExecutor.get(id); Model m = getModelSnapshot(id, runnable); String modelId = modelCollection.add(m); logger.info("model with id created {}", modelId); return modelId; } protected Project toProject(String id, Model m) { ModelRunnable runnable = modelExecutor.get(id); boolean isRunning = false; if (runnable != null) { isRunning = runnable.isRunning(); } Project p = new Project(); p.setId(id); p.setName(m.getName()); p.setTime(m.getTime()); p.setRunning(isRunning); HistoryPoint lastHistoryPoint = null; for(MovingObject mo : m.getMovingObjects()) { Texture texture = new Texture(); if (mo instanceof CelestialBody) { CelestialBody celestialBody = (CelestialBody) mo; texture.setName(mo.getName()); texture.setTextureFileName(celestialBody.getTextureFileName()); p.getCelestialBodies().add(texture); } else if (mo instanceof Spacecraft) { Spacecraft spacecraft = (Spacecraft) mo; if (!spacecraft.getNamedHistoryPoints().isEmpty()) { lastHistoryPoint = compareHistoryPoint(lastHistoryPoint, spacecraft.getNamedHistoryPoints().get(spacecraft.getNamedHistoryPoints().size()-1)); } } } p.setLastHistoryPoint(lastHistoryPoint); return p; } protected HistoryPoint compareHistoryPoint(HistoryPoint hp1, HistoryPoint hp2) { if (hp1 == null) { return hp2; } else if (hp2 == null) { return hp1; } else { if (hp1.getTimestamp().compareTo(hp2.getTimestamp())>=0) { return hp1; } else { return hp2; } } } protected Model getModelSnapshot(String id, ModelRunnable runnable) { if (runnable.isRunning()) { Model m = modelExecutor.stop(id); Model result = modelSerializer.clone(m); modelCollection.update(id, m); modelExecutor.create(m, id); return result; } else { Model m = runnable.getModel(); Model result = modelSerializer.clone(m); return result; } } }