package org.develnext.jphp.json.gson; import com.google.gson.*; import php.runtime.Memory; import php.runtime.env.Environment; import php.runtime.lang.StdClass; import php.runtime.memory.ArrayMemory; import php.runtime.memory.DoubleMemory; import php.runtime.memory.ObjectMemory; import php.runtime.memory.StringMemory; import java.lang.ref.WeakReference; import java.lang.reflect.Type; import java.util.Map; public class MemoryDeserializer implements JsonDeserializer<Memory> { protected boolean assoc; protected int maxDepth = 512; protected WeakReference<Environment> env; public boolean isAssoc() { return assoc; } public void setEnv(Environment env) { this.env = new WeakReference<Environment>(env); } public void setAssoc(boolean assoc) { this.assoc = assoc; } public int getMaxDepth() { return maxDepth; } public void setMaxDepth(int maxDepth) { this.maxDepth = maxDepth; } protected Memory convert(JsonElement json, int depth) { if (depth > maxDepth) throw new MaxDepthException(); if (json.isJsonNull()) return Memory.NULL; if (json.isJsonPrimitive()) { JsonPrimitive jsonPrimitive = json.getAsJsonPrimitive(); if (jsonPrimitive.isString()) return StringMemory.valueOf(jsonPrimitive.getAsString()); else if (jsonPrimitive.isBoolean()) return jsonPrimitive.getAsBoolean() ? Memory.TRUE : Memory.FALSE; else if (jsonPrimitive.isNumber()) { Memory l = StringMemory.toLong(jsonPrimitive.getAsString()); if (l != null) return l; else return new DoubleMemory(json.getAsDouble()); } return Memory.NULL; } else if (json.isJsonArray()) { ArrayMemory array = new ArrayMemory(); for(JsonElement el : json.getAsJsonArray()) array.add(convert(el, depth + 1).toImmutable()); return array.toConstant(); } else if (json.isJsonObject()) { JsonObject jsonObject = json.getAsJsonObject(); StdClass stdClass = assoc ? null : new StdClass(env.get()); ArrayMemory array = assoc ? new ArrayMemory() : stdClass.getProperties(); for(Map.Entry<String, JsonElement> el : jsonObject.entrySet()){ String key = el.getKey(); if (!key.startsWith("\0")) array.put(key, convert(el.getValue(), depth + 1).toImmutable()); } return assoc ? array : new ObjectMemory(stdClass); } else return Memory.NULL; } @Override public Memory deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { return convert(json, 0); } public static class MaxDepthException extends RuntimeException { @Override public synchronized Throwable fillInStackTrace() { return this; } } }