diff --git a/src/main/java/com/icedberries/UBFunkeysServer/Galaxy/GalaxyServer.java b/src/main/java/com/icedberries/UBFunkeysServer/Galaxy/GalaxyServer.java index ab0553c..702df84 100644 --- a/src/main/java/com/icedberries/UBFunkeysServer/Galaxy/GalaxyServer.java +++ b/src/main/java/com/icedberries/UBFunkeysServer/Galaxy/GalaxyServer.java @@ -2,10 +2,9 @@ package com.icedberries.UBFunkeysServer.Galaxy; import com.icedberries.UBFunkeysServer.ArkOne.ArkOneParser; import com.icedberries.UBFunkeysServer.domain.Crib; -import com.icedberries.UBFunkeysServer.service.CribService; -import com.icedberries.UBFunkeysServer.service.EmailService; -import com.icedberries.UBFunkeysServer.service.FileService; -import com.icedberries.UBFunkeysServer.util.RDFUtil; +import com.icedberries.UBFunkeysServer.domain.Level; +import com.icedberries.UBFunkeysServer.domain.User; +import com.icedberries.UBFunkeysServer.service.*; import org.apache.commons.lang3.StringUtils; import org.apache.tomcat.util.http.fileupload.IOUtils; import org.springframework.beans.factory.annotation.Autowired; @@ -13,11 +12,7 @@ import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.util.FileCopyUtils; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; import org.springframework.web.servlet.HandlerMapping; import org.w3c.dom.Document; import org.w3c.dom.Element; @@ -32,12 +27,16 @@ import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.TransformerException; -import java.io.*; -import java.nio.charset.StandardCharsets; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.StringReader; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; import java.util.concurrent.ThreadLocalRandom; -import static java.nio.charset.StandardCharsets.UTF_8; - @RestController public class GalaxyServer { @@ -48,7 +47,13 @@ public class GalaxyServer { private CribService cribService; @Autowired - FileService fileService; + private LevelService levelService; + + @Autowired + private UserService userService; + + @Autowired + private FileService fileService; /** * This is only used as part of the updater to pass files to the client as requested via URL path @@ -116,7 +121,7 @@ public class GalaxyServer { @PostMapping("/") public ResponseEntity GalaxyPostResponse(@RequestBody String xmlBody) { // Log the request - System.out.println("[Galaxy][POST] New Request: " + xmlBody); + System.out.println("[Galaxy][POST] Request: " + xmlBody); try { // Parse the xml body of the request @@ -130,23 +135,41 @@ public class GalaxyServer { String command = nodes.item(0).getNodeName(); // Handle based on the root element + ResponseEntity response; switch(command) { case "postcard": - return sendPostcard((Element)nodes.item(0)); + response = sendPostcard((Element)nodes.item(0)); + break; case "savecrib": - return saveCrib(nodes.item(0)); + response = saveCrib(nodes.item(0)); + break; case "loadcrib": - return loadCrib((Element)nodes.item(0)); + response = loadCrib((Element)nodes.item(0)); + break; case "get_sh_levels": - return getShLevels((Element)nodes.item(0)); + response = getShLevels((Element)nodes.item(0)); + break; case "get_level": - return getLevel((Element)nodes.item(0)); + response = getLevel((Element)nodes.item(0)); + break; case "add_level": - return addLevel((Element)nodes.item(0)); + response = addLevel((Element)nodes.item(0)); + break; + case "save_level": + response = saveLevel((Element)nodes.item(0)); + break; + case "get_top": + response = getTop((Element)nodes.item(0)); + break; default: System.out.println("[Galaxy][POST][ERROR] Unhandled type of request for: " + command); return new ResponseEntity<>(HttpStatus.BAD_REQUEST); } + // Log the response + System.out.println(response.getBody()); + + // Return to the client + return response; } catch (ParserConfigurationException | IOException | SAXException e) { System.out.println("[Galaxy][POST][ERROR] Thrown Error: "); e.printStackTrace(); @@ -155,8 +178,6 @@ public class GalaxyServer { } private ResponseEntity loadCrib(Element element) { - System.out.println("[Galaxy][POST] loadcrib request received"); - /* * 0 - Success * 1 - Error Loading Crib / Can't find a crib with that name (need to test codes) @@ -224,8 +245,6 @@ public class GalaxyServer { } private ResponseEntity saveCrib(Node node) { - System.out.println("[Galaxy][POST] savecrib request received"); - /* * 0 - Success * 1 - Error Saving Crib / Crib already exists (need to test codes) @@ -296,8 +315,6 @@ public class GalaxyServer { } private ResponseEntity sendPostcard(Element element) { - System.out.println("[Galaxy][POST] postcard request received"); - // Parse data from the request String to = element.getAttribute("to"); String subject = element.getAttribute("subject"); @@ -315,22 +332,168 @@ public class GalaxyServer { return new ResponseEntity<>(response, HttpStatus.OK); } + // ACE AND MULCH's GAMES RESPONSE CODES + // 0 - Success + // 1 - User Not Authorized + // 2 - There was a problem with your request, try again later + // 3 - Name already exists on server + // 4 - Cannot find a game with that name + private ResponseEntity getShLevels(Element element) throws IOException { - System.out.println("[Galaxy][POST] get_sh_levels request received"); + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append(""); - //TODO: GET THE LEVELS SAVED ON THE SERVER + List sharedLevels = levelService.getLevelsByUserId(Integer.valueOf(element.getAttribute("uid"))); - return new ResponseEntity<>("", HttpStatus.OK); + if (sharedLevels.isEmpty()) { + // No shared levels + stringBuilder.append(""); + } else { + // Add their shared levels to the list + for (Level level : sharedLevels) { + stringBuilder.append(""); + } + stringBuilder.append(""); + } + stringBuilder.append(""); + + return new ResponseEntity<>(stringBuilder.toString(), HttpStatus.OK); } private ResponseEntity getLevel(Element element) { - //TODO: DO THIS - return new ResponseEntity<>("", HttpStatus.OK); + Integer levelId = Integer.valueOf(element.getAttribute("id")); + Level level = levelService.findLevelById(levelId).orElse(null); + + String levelData = level == null ? "" : level.getLevelData(); + + //TODO: NOT SURE WHICH IS CORRECT? + //return new ResponseEntity<>("" + levelData + "", HttpStatus.OK); + return new ResponseEntity<>("" + levelData + "", HttpStatus.OK); } private ResponseEntity addLevel(Element element) { - //TODO: DO THIS - return new ResponseEntity<>("", HttpStatus.OK); + int responseCode = 0; + + String levelName = element.getAttribute("n"); + String gameName = element.getAttribute("gn"); + + // Check to see if the level with that name already is saved on the server + if (levelService.existsByLevelNameAndGameName(levelName, gameName)) { + //TODO: ADD A CHECK TO OVERRIDE IF SAME PERSON (NOT SURE IF ALLOWED AT ALL ANYWAYS) + responseCode = 3; + } + + // Return to the client + return new ResponseEntity<>("", HttpStatus.OK); + } + + private ResponseEntity saveLevel(Element element) { + int responseCode = 0; + + String levelName = element.getAttribute("n"); + String tnurl = element.getAttribute("tnurl"); + String gameName = element.getAttribute("gn"); + Integer uid = Integer.valueOf(element.getAttribute("uid")); + + String levelData = ""; + try { + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + factory.setNamespaceAware(true); + DocumentBuilder builder = factory.newDocumentBuilder(); + Document newDocument = builder.newDocument(); + Node importedNode = newDocument.importNode(element.getFirstChild(), true); + newDocument.appendChild(importedNode); + + levelData = ArkOneParser.RemoveXMLTag(newDocument); + } catch (ParserConfigurationException | TransformerException e) { + System.out.println("[Galaxy][POST] Exception thrown when saving crib: "); + e.printStackTrace(); + responseCode = 1; + } + + Level level = Level.builder() + .userId(uid) + .levelName(levelName) + .gameName(gameName) + .levelData(levelData) + .sharedDate(LocalDateTime.now()) + .imagePath(tnurl) + .build(); + + Level savedLevel = levelService.save(level); + + Integer levelId = 0; + + if (savedLevel == null) { + responseCode = 2; + } else { + levelId = savedLevel.getId(); + } + + //TODO: THIS MIGHT BE WRONG? + //TODO: MIGHT NEED TO UPDATE TO ACCOUNT FOR UPDATING ALREADY UPLOADED LEVELS + return new ResponseEntity<>("", HttpStatus.OK); + } + + private ResponseEntity getTop(Element element) { + // Get the game name + String gameName = element.getAttribute("gn"); + String type = element.getAttribute("t"); + int count = Integer.parseInt(element.getAttribute("c")); + + List allLevelsWithName = levelService.findAllByGameName(gameName); + List filteredLevels = new ArrayList<>(); + + int maxSize = Math.min(count, allLevelsWithName.size()); + // Switch based on what type of getTop it is + switch (type) { + case "b": + // Best Levels + //TODO: Sort them by highest whatever + + // Filter down to the top X levels + for (int i = 0; i < maxSize; i++) { + //TODO: SWITCH THIS TO USE THE SORTED LEVELS + filteredLevels.add(allLevelsWithName.get(i)); + } + break; + case "r": + // Random Level + + break; + case "l": + // Latest Levels + + break; + default: + // Unhandled type + System.out.println("[Galaxy][POST] Unhandled type: " + type); + break; + } + + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append(""); + + if (filteredLevels.isEmpty()) { + // No levels match + stringBuilder.append(""); + } else { + // Add all the found levels to the response + for (Level level : filteredLevels) { + //TODO: THIS IS BROKEN + //stringBuilder.append(""); + //stringBuilder.append(level.getLevelData()); + //stringBuilder.append(""); + stringBuilder.append(""); + } + } + + stringBuilder.append(("")); + + return new ResponseEntity<>(stringBuilder.toString(), HttpStatus.OK); } /* diff --git a/src/main/java/com/icedberries/UBFunkeysServer/domain/Level.java b/src/main/java/com/icedberries/UBFunkeysServer/domain/Level.java new file mode 100644 index 0000000..9acd4f3 --- /dev/null +++ b/src/main/java/com/icedberries/UBFunkeysServer/domain/Level.java @@ -0,0 +1,36 @@ +package com.icedberries.UBFunkeysServer.domain; + +import lombok.*; +import org.hibernate.annotations.Type; + +import javax.persistence.*; +import java.time.LocalDateTime; + +@Getter +@Setter +@Builder +@NoArgsConstructor +@AllArgsConstructor +@Entity +@Table(name = "GameMakerLevels") +public class Level { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Integer id; + + private Integer userId; + + // BOMBER or RECYCLE + private String gameName; + + private String levelName; + + @Column(columnDefinition = "MEDIUMTEXT") + @Type(type = "org.hibernate.type.TextType") + private String levelData; + + private LocalDateTime sharedDate; + + private String imagePath; +} diff --git a/src/main/java/com/icedberries/UBFunkeysServer/repository/LevelRepository.java b/src/main/java/com/icedberries/UBFunkeysServer/repository/LevelRepository.java new file mode 100644 index 0000000..9ebbac7 --- /dev/null +++ b/src/main/java/com/icedberries/UBFunkeysServer/repository/LevelRepository.java @@ -0,0 +1,28 @@ +package com.icedberries.UBFunkeysServer.repository; + +import com.icedberries.UBFunkeysServer.domain.Level; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.CrudRepository; +import org.springframework.data.repository.query.Param; +import org.springframework.stereotype.Repository; + +import java.util.List; +import java.util.Optional; + +@Repository +public interface LevelRepository extends CrudRepository { + + @Query("select level from Level level where level.levelName = :levelName") + Optional getLevelByName(@Param("levelName") String levelName); + + @Query("select level from Level level where level.userId = :userId") + List getLevelsByUserId(@Param("userId") Integer userId); + + Boolean existsByLevelNameAndGameName(String levelName, String gameName); + + @Query("select level from Level level where level.gameName = :gameName") + List findAllByGameName(@Param("gameName") String gameName); + + @Query("select level from Level level where level.id = :id") + Optional findLevelById(@Param("id") Integer id); +} diff --git a/src/main/java/com/icedberries/UBFunkeysServer/service/LevelService.java b/src/main/java/com/icedberries/UBFunkeysServer/service/LevelService.java new file mode 100644 index 0000000..cff937d --- /dev/null +++ b/src/main/java/com/icedberries/UBFunkeysServer/service/LevelService.java @@ -0,0 +1,21 @@ +package com.icedberries.UBFunkeysServer.service; + +import com.icedberries.UBFunkeysServer.domain.Level; + +import java.util.List; +import java.util.Optional; + +public interface LevelService { + + Optional getLevelByName(String levelName); + + List getLevelsByUserId(Integer userId); + + Boolean existsByLevelNameAndGameName(String levelName, String gameVersion); + + Level save(Level level); + + List findAllByGameName(String gameName); + + Optional findLevelById(Integer id); +} diff --git a/src/main/java/com/icedberries/UBFunkeysServer/service/impl/LevelServiceImpl.java b/src/main/java/com/icedberries/UBFunkeysServer/service/impl/LevelServiceImpl.java new file mode 100644 index 0000000..06273c1 --- /dev/null +++ b/src/main/java/com/icedberries/UBFunkeysServer/service/impl/LevelServiceImpl.java @@ -0,0 +1,47 @@ +package com.icedberries.UBFunkeysServer.service.impl; + +import com.icedberries.UBFunkeysServer.domain.Level; +import com.icedberries.UBFunkeysServer.repository.LevelRepository; +import com.icedberries.UBFunkeysServer.service.LevelService; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Optional; + +@Service +@RequiredArgsConstructor +public class LevelServiceImpl implements LevelService { + + private final LevelRepository levelRepository; + + @Override + public Optional getLevelByName(String levelName) { + return levelRepository.getLevelByName(levelName); + } + + @Override + public List getLevelsByUserId(Integer userId) { + return levelRepository.getLevelsByUserId(userId); + } + + @Override + public Boolean existsByLevelNameAndGameName(String levelName, String gameVersion) { + return levelRepository.existsByLevelNameAndGameName(levelName, gameVersion); + } + + @Override + public Level save(Level level) { + return levelRepository.save(level); + } + + @Override + public List findAllByGameName(String gameName) { + return levelRepository.findAllByGameName(gameName); + } + + @Override + public Optional findLevelById(Integer id) { + return levelRepository.findLevelById(id); + } +}