Java tutorial
package com.github.fcannizzaro.resourcer; import com.github.fcannizzaro.resourcer.annotations.*; import com.github.fcannizzaro.resourcer.util.FileUtils; import com.github.fcannizzaro.resourcer.util.RequestUtils; import org.json.JSONArray; import org.json.JSONObject; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NodeList; import javax.imageio.ImageIO; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.UnsupportedAudioFileException; import java.awt.*; import java.io.File; import java.io.IOException; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.net.URL; import java.util.HashMap; /** * The MIT License (MIT) * <p> * Copyright (c) 2016 Francesco Cannizzaro * <p> * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated * documentation files (the "Software"), to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: * <p> * The above copyright notice and this permission notice shall be included in all copies or substantial portions * of the Software. * <p> * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ @SuppressWarnings("unused") public class Resourcer { // directory paths public static String PATH_BASE; public static String IMAGE_DIR = "images" + File.separator; public static String AUDIO_DIR = "audio" + File.separator; public static String JSON_DIR = "json" + File.separator; public static String VALUES_DIR = "values" + File.separator; // values types public final static String STRING = "string"; public final static String INTEGER = "integer"; public final static String COLOR = "color"; public final static String LONG = "long"; public final static String DOUBLE = "double"; public final static String FLOAT = "float"; public final static String BOOLEAN = "boolean"; public final static String[] elements = { STRING, INTEGER, FLOAT, DOUBLE, LONG, BOOLEAN, COLOR }; // values public static HashMap<String, HashMap<String, Object>> values = new HashMap<String, HashMap<String, Object>>(); /** * Setup initial Resourcer properties */ public static class Builder { public Builder(String pathBase) { PATH_BASE = pathBase + File.separator; } public Builder setImageDir(String path) { IMAGE_DIR = path + File.separator; return this; } public Builder setAudioDir(String path) { AUDIO_DIR = path + File.separator; return this; } public Builder setJsonDir(String path) { JSON_DIR = path + File.separator; return this; } public Builder setValuesDir(String path) { VALUES_DIR = path + File.separator; return this; } public void build() { findValues(); } } /** * Bind a class */ public static void bind(Object annotated) { for (Field field : annotated.getClass().getDeclaredFields()) try { switchAnnotation(field, annotated); } catch (IllegalAccessException e) { e.printStackTrace(); } } /** * Check the field annotation and execute its method * * @throws IllegalAccessException */ private static void switchAnnotation(Field field, Object annotated) throws IllegalAccessException { // File com.github.fcannizzaro.resourcer.annotations.Image image = field .getAnnotation(com.github.fcannizzaro.resourcer.annotations.Image.class); Audio audio = field.getAnnotation(Audio.class); Json json = field.getAnnotation(Json.class); // Values StringRes stringRes = field.getAnnotation(StringRes.class); IntegerRes integerRes = field.getAnnotation(IntegerRes.class); FloatRes floatRes = field.getAnnotation(FloatRes.class); DoubleRes doubleRes = field.getAnnotation(DoubleRes.class); LongRes longRes = field.getAnnotation(LongRes.class); BooleanRes booleanRes = field.getAnnotation(BooleanRes.class); ColorRes colorRes = field.getAnnotation(ColorRes.class); // grant access field.setAccessible(true); if (image != null) { annotateImage(field, image, annotated); return; } if (audio != null) { annotateAudio(field, audio, annotated); return; } if (json != null) { annotateJson(field, json, annotated); return; } if (stringRes != null && is(field, String.class)) { annotate(field, STRING, stringRes.value(), annotated); return; } if (integerRes != null) { annotate(field, INTEGER, integerRes.value(), annotated); return; } if (floatRes != null) { annotate(field, FLOAT, floatRes.value(), annotated); return; } if (doubleRes != null) { annotate(field, DOUBLE, doubleRes.value(), annotated); return; } if (longRes != null) { annotate(field, BOOLEAN, longRes.value(), annotated); return; } if (booleanRes != null) { annotate(field, BOOLEAN, booleanRes.value(), annotated); return; } if (colorRes != null && is(field, Color.class)) annotate(field, COLOR, colorRes.value(), annotated); } /* Annotation parsing */ /** * Create and BufferedImage and update the field * * @throws IllegalAccessException */ private static void annotateImage(Field field, com.github.fcannizzaro.resourcer.annotations.Image annotation, Object annotated) throws IllegalAccessException { try { String path = annotation.value(); boolean pathAbsolute = FileUtils.isPathAbsolute(path); String res = getPath(path, IMAGE_DIR); if (path.startsWith("http")) field.set(annotated, ImageIO.read(new URL(path))); else field.set(annotated, ImageIO.read(pathAbsolute ? new File(path) : new File(res))); } catch (IOException e) { e.printStackTrace(); } } /** * Create and AudioInputStream and update the field * * @throws IllegalAccessException */ private static void annotateAudio(Field field, Audio annotation, Object annotated) throws IllegalAccessException { try { String res = getPath(annotation.value(), AUDIO_DIR); field.set(annotated, AudioSystem.getAudioInputStream(new File(res))); } catch (IOException | UnsupportedAudioFileException e) { e.printStackTrace(); } } /** * Create a JSONObject / JSONArray from a file * * @throws IllegalAccessException */ private static void annotateJson(Field field, Json annotation, Object annotated) throws IllegalAccessException { String url = annotation.url(), key = annotation.key(), path = annotation.value(), content; boolean isUrl = !url.equals("null") || path.startsWith("http"), pathAbsolute = FileUtils.isPathAbsolute(path); if (hasDotNotation(annotation) && !isUrl || isUrl && !key.equals("null")) { annotateJsonDotNotation(field, annotation, annotated); return; } if (!isUrl) content = FileUtils.read(pathAbsolute ? path + ".json" : getPath(path + ".json", JSON_DIR)); else content = RequestUtils.get(url.equals("null") ? path : url); if (content == null) return; if (is(field, JSONArray.class)) field.set(annotated, new JSONArray(content)); else if (is(field, JSONObject.class)) field.set(annotated, new JSONObject(content)); } /** * Read key / object from a json file * * @throws IllegalAccessException */ private static void annotateJsonDotNotation(Field field, Json annotation, Object annotated) throws IllegalAccessException { String[] values = annotation.value().split("\\."); boolean pathAbsolute = FileUtils.isPathAbsolute(values[0]); String dotNotation = annotation.key(), url = annotation.url(), content; if (!dotNotation.equals("null") && !url.equals("null")) { content = RequestUtils.get(url); String[] parts = dotNotation.split("\\."); values = new String[parts.length + 1]; System.arraycopy(parts, 0, values, 1, parts.length); } else content = FileUtils.read((pathAbsolute ? values[0] + ".json" : getPath(values[0] + ".json", JSON_DIR))); if (content == null) return; // create json object JSONObject object = new JSONObject(content); for (int i = 1; i < values.length; i++) { String key = values[i]; if (i == values.length - 1) { if (object.has(key)) field.set(annotated, object.get(key)); } else object = object.getJSONObject(key); } } /** * Read a parsed value * * @throws IllegalAccessException */ private static void annotate(Field field, String type, String name, Object annotated) throws IllegalAccessException { if (name.equals("null")) name = field.getName(); field.set(annotated, values.get(type).get(name)); } /* Util methods */ /** * Parse values xml files */ private static void findValues() { values = new HashMap<>(); File dir = new File(PATH_BASE + VALUES_DIR); if (!dir.isDirectory()) return; File[] files = dir.listFiles(); if (files == null) return; for (File file : files) // only *.xml files if (file.getName().matches(".*\\.xml$")) { Document doc = FileUtils.readXML(file.getAbsolutePath()); if (doc == null) return; Element ele = doc.getDocumentElement(); for (String element : elements) { NodeList list = ele.getElementsByTagName(element); if (values.get(element) == null) values.put(element, new HashMap<>()); for (int j = 0; j < list.getLength(); j++) { Element node = (Element) list.item(j); String value = node.getFirstChild().getNodeValue(); Object valueDefined = value; switch (element) { case INTEGER: valueDefined = Integer.valueOf(value); break; case DOUBLE: valueDefined = Double.valueOf(value); break; case FLOAT: valueDefined = Float.valueOf(value); break; case BOOLEAN: valueDefined = Boolean.valueOf(value); break; case LONG: valueDefined = Long.valueOf(value); break; case COLOR: if (value.matches("@color/.*")) { try { Class<?> c = Class.forName("com.github.fcannizzaro.material.Colors"); Object colors = c.getDeclaredField(value.replace("@color/", "")).get(c); Method asColor = c.getMethod("asColor"); valueDefined = asColor.invoke(colors); } catch (Exception e) { System.out.println("ERROR Resourcer - Cannot bind " + value); } } else valueDefined = Color.decode(value); break; } values.get(node.getNodeName()).put(node.getAttribute("name"), valueDefined); } } } } /** * Build path string */ private static String getPath(String name, String dir) { return PATH_BASE + dir + name; } /** * Check if field class is the expected class */ private static boolean is(Field field, Class expected) { return field.getType().equals(expected); } /** * Check if annotation value has a dot notation */ private static boolean hasDotNotation(Json annotation) { return annotation.value().matches("^(?!http?)[\\w:\\\\/]+(\\.\\w+)+$"); } }