package jp.ac.aiit.jointry.util; import jp.ac.aiit.jointry.services.broker.util.Base64; import jp.ac.aiit.jointry.services.broker.util.ImageUtil; import com.fasterxml.jackson.core.JsonGenerationException; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.io.PrintWriter; import java.net.MalformedURLException; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.logging.Level; import java.util.logging.Logger; import javafx.embed.swing.SwingFXUtils; import javafx.scene.Node; import javafx.scene.image.Image; import javafx.scene.image.WritableImage; import javax.imageio.ImageIO; import jp.ac.aiit.jointry.models.Costume; import jp.ac.aiit.jointry.models.Jty; import jp.ac.aiit.jointry.models.Sprite; import jp.ac.aiit.jointry.models.Status; import jp.ac.aiit.jointry.models.blocks.Block; import jp.ac.aiit.jointry.models.blocks.expression.Expression; import jp.ac.aiit.jointry.models.blocks.statement.Statement; import jp.ac.aiit.jointry.services.file.FileManager; public class JsonUtil { public static final ObjectMapper objectMapper = new ObjectMapper(); public static final String SPRITE_TAG = "sprite"; public static final String COSTUME_TAG = "costume"; public static final String SCRIPT_TAG = "script"; public static final String TYPE_BASE64 = "base64"; public static final String TYPE_FILE = "file"; public static String convertObjectToJsonString(Object obj) { try { return objectMapper.writeValueAsString(obj); } catch (JsonProcessingException ex) { return ""; } } public static List convertJsonStringToList(String jsonString) { List list = new ArrayList(); try { list = objectMapper.readValue(jsonString, ArrayList.class); } catch (IOException ex) { Logger.getLogger(JsonUtil.class.getName()).log(Level.SEVERE, null, ex); } return list; } public static Map<String, String> processSprite(Sprite sprite) { Map<String, String> spriteMap = new HashMap(); spriteMap.put("title", sprite.getName()); spriteMap.put("layoutX", Double.toString(sprite.getTranslateX())); spriteMap.put("layoutY", Double.toString(sprite.getTranslateY())); spriteMap.put("costume", Integer.toString(sprite.getCostumeNumber())); spriteMap.put("rotate", Double.toString(sprite.getRotate())); String speech = sprite.getSpeech(); if (speech != null) { spriteMap.put("speech", speech); } return spriteMap; } public static ArrayList<Map> processCostumes(Sprite sprite, String dir) { ArrayList<Map> costumes = new ArrayList(); for (Costume costume : sprite.getCostumes()) { Map<String, String> costumeMap = new HashMap(); costumeMap.put("title", costume.getTitle()); String fileName = sprite.getName() + "_costume" + costume.getNumber() + ".png"; costumeMap.put("img_src", fileName); saveImage(new File(dir, "img"), fileName, costume.getImage()); costumeMap.put("img", Base64.encode(dir + "/img/" + fileName)); costumes.add(costumeMap); } return costumes; } public static Map<String, String> processScript(Sprite sprite, String dir) { ArrayList<Map> source = new ArrayList(); for (Node node : sprite.getScriptPane().getChildrenUnmodifiable()) { if (node instanceof Statement) { Statement procedure = (Statement) node; if (procedure.isTopLevelBlock()) { Map<String, Object> blockInfo = new HashMap(); blockInfo.put("coordinate", procedure.getLayoutX() + " " + procedure.getLayoutY()); blockInfo.put("block", BlockUtil.getAllStatus(procedure)); source.add(blockInfo); } } else if (node instanceof Expression) { Expression exp = (Expression) node; if (!exp.hasMother()) { Map<String, Object> blockInfo = new HashMap(); blockInfo.put("coordinate", exp.getLayoutX() + " " + exp.getLayoutY()); blockInfo.put("block", BlockUtil.getStatus(exp)); source.add(blockInfo); } } } Map<String, String> map = new HashMap<>(); String name = sprite.getName() + "_script"; String contents = convertObjectToJsonString(source); saveScriptFile(dir, name, contents); map.put("script_src", name); map.put("script", contents); return map; } public static Status parseJSONString(String jsonString) { Status status = null; TypeReference type = new TypeReference<Status>() { }; try { status = objectMapper.readValue(jsonString, type); } catch (JsonGenerationException ex) { Logger.getLogger(FileManager.class.getName()).log(Level.SEVERE, null, ex); } catch (JsonMappingException ex) { Logger.getLogger(FileManager.class.getName()).log(Level.SEVERE, null, ex); } catch (IOException ex) { Logger.getLogger(FileManager.class.getName()).log(Level.SEVERE, null, ex); } return status; } public static Sprite parseJSONStringToSprite(String jsonString, File file) throws MalformedURLException, FileNotFoundException, IOException { Jty jty = objectMapper.readValue(jsonString, Jty.class); // load sprite Map<String, String> spriteMap = jty.getSprite(); Sprite sprite = new Sprite(); sprite.setName(spriteMap.get("title")); sprite.setTranslateX(Double.valueOf(spriteMap.get("layoutX"))); sprite.setTranslateY(Double.valueOf(spriteMap.get("layoutY"))); sprite.setRotate(Double.valueOf(spriteMap.get("rotate"))); String speech = spriteMap.get("speech"); if (speech != null) { sprite.setSpeechBubble(speech); } // load costume List<Map> costumes = jty.getCostume(); parseJSONStringToCostumes(sprite, costumes, file); sprite.setSpriteCostume(Integer.parseInt(spriteMap.get("costume"))); // load script Map<String, String> scriptMap = jty.getScript(); String parentPath = file.getParent(); File scriptFile = new File(parentPath, scriptMap.get("script_src")); if (scriptFile.exists()) { try (BufferedReader br = new BufferedReader(new FileReader(scriptFile))) { String line = br.readLine(); if (line != null) { parseJSONStringToBlocks(line, sprite); } } } else { parseJSONStringToBlocks(scriptMap.get("script"), sprite); } return sprite; } public static void parseJSONStringToCostumes(Sprite sprite, List<Map> costumes, File file) throws MalformedURLException { for (Map<String, String> costumeMap : costumes) { String title = costumeMap.get("title"); String parentPath = file.getParent(); File imgFile = new File(parentPath + "/img", costumeMap.get("img_src")); if (imgFile.exists()) { sprite.addCostume(title, new Image(imgFile.toURI().toURL().toString())); } else { // decode Base64 String value = costumeMap.get("img"); List<String> list = new ArrayList(); list.addAll(Arrays.asList(value.split("\n"))); WritableImage img = SwingFXUtils.toFXImage(ImageUtil.createImage(list), null); sprite.addCostume(title, img); } } } private static void parseJSONStringToBlocks(String jsonString, Sprite sprite) { ArrayList<Map> source = null; try { source = objectMapper.readValue(jsonString, ArrayList.class); } catch (IOException ex) { Logger.getLogger(JsonUtil.class .getName()).log(Level.SEVERE, null, ex); } for (Map blocks_info : source) { Block topBlock = null; Block prevBlock = null; Object blocks = blocks_info.get("block"); if (blocks instanceof ArrayList) { for (Map status_info : ((ArrayList<Map>) blocks)) { Block block = BlockUtil.create(status_info); block.setSprite(sprite); Status status = BlockUtil.convertMapToStatus(status_info.get(block.getClass().getSimpleName())); block.setStatus(status); if (topBlock == null) { topBlock = block; prevBlock = topBlock; } else if (prevBlock != null) { ((Statement) prevBlock).addLink((Statement) block); prevBlock = block; } } } else { Map status_info = ((Map) blocks); Block block = BlockUtil.create(status_info); block.setSprite(sprite); Status status = BlockUtil.convertMapToStatus(status_info.get(block.getClass().getSimpleName())); block.setStatus(status); String cordinate = (String) blocks_info.get("coordinate"); String[] pos = cordinate.split(" "); double x = Double.valueOf(pos[0]); double y = Double.valueOf(pos[1]); block.move(x, y); //子要素含めて全ての座標を設定 block.show(); } if (topBlock != null) { ((Statement) topBlock).fetchPrevTopBlock(); //topblockの座標 String cordinate = (String) blocks_info.get("coordinate"); String[] pos = cordinate.split(" "); double x = Double.valueOf(pos[0]); double y = Double.valueOf(pos[1]); topBlock.move(x, y); //子要素含めて全ての座標を設定 topBlock.show(); } } } private static void saveImage(File dir, String name, Image image) { if (!dir.exists()) { dir.mkdirs(); //create img folder } File fileName = new File(dir.getPath(), name); try { ImageIO.write(SwingFXUtils.fromFXImage(image, null), "png", fileName); } catch (IOException ex) { Logger.getLogger(FileManager.class .getName()).log(Level.SEVERE, null, ex); } } private static void saveScriptFile(String dir, String name, String content) { try (PrintWriter script = new PrintWriter(new File(dir, name))) { script.print(content); script.flush(); } catch (FileNotFoundException ex) { Logger.getLogger(JsonUtil.class .getName()).log(Level.SEVERE, null, ex); } } }