package org.minimalj.rest;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.minimalj.frontend.impl.json.JsonReader;
import org.minimalj.model.properties.Properties;
import org.minimalj.model.properties.PropertyInterface;
import org.minimalj.util.CloneHelper;
import org.minimalj.util.FieldUtils;
import org.minimalj.util.StringUtils;

public class EntityJsonReader extends JsonReader {

	public <T> T read(Class<T> clazz, String input) {
		if (StringUtils.isEmpty(input)) {
			return null;
		}
		Map<String, Object> values = (Map<String, Object>) super.read(input);
		return convert(clazz, values);
	}

	private <T> List<T> convertList(Class<T> clazz, List list) {
		List convertedList = new ArrayList<>();
		for (Object item : list) {
			convertedList.add(convert(clazz, (Map<String, Object>) item));
		}
		return convertedList;
	}

	private <T extends Enum> void convertEnumSet(Set<T> set, Class<T> clazz, List list) {
		set.clear();
		for (Object item : list) {
			set.add(Enum.valueOf(clazz, (String) item));
		}
	}

	private <T> T convert(Class<T> clazz, Map<String, Object> values) {
		T entity = CloneHelper.newInstance(clazz);

		Map<String, PropertyInterface> properties = Properties.getProperties(clazz);
		for (Map.Entry<String, Object> entry : values.entrySet()) {
			PropertyInterface property = properties.get(entry.getKey());
			if (property == null) {
				continue;
			}
			Object value = entry.getValue();
			if (property.getClazz() == List.class) {
				List list = (List) values;
				value = convertList((Class) property.getType(), list);
			} else if (property.getClazz() == Set.class) {
				Set set = (Set) property.getValue(entity);
				convertEnumSet(set, (Class) property.getType(), (List)value);
			} else if (value instanceof String) {
				String string = (String) value;
				Class<?> propertyClazz = property.getClazz();
				value = FieldUtils.parse(string, propertyClazz);
				property.setValue(entity, value);
			} else if (value instanceof Boolean) {
				property.setValue(entity, value);
			} else if (value instanceof Map) {
				Map map = (Map) value;
				Class c2 = property.getClazz();
				value = convert(c2, map);
				property.setValue(entity, value);
			}
		}
		return entity;
	}
	
}

@@ -19,24 +19,53 @@
 lj.rest;%0D%0A%0D%0A
+import java.io.InputStream;%0D%0A
 import java.
@@ -77,24 +77,24 @@
 ArrayList;%0D%0A
-
 import java.
@@ -238,24 +238,28 @@
 .properties.
+Flat
 Properties;%0D
@@ -705,24 +705,207 @@
 alues);%0D%0A%09%7D%0D
+%0A%09%0D%0A%09public %3CT%3E T read(Class%3CT%3E clazz, InputStream inputStream) %7B%0D%0A%09%09Map%3CString, Object%3E values = (Map%3CString, Object%3E) super.read(inputStream);%0D%0A%09%09return convert(clazz, values);%0D%0A%09%7D%0D
 %0A%0D%0A%09private 
@@ -1492,16 +1492,20 @@
 rties = 
+Flat
 Properti
@@ -2118,32 +2118,213 @@
 String) value;%0D%0A
+%09%09%09%09if (%22version%22.equals(property.getName())) %7B%0D%0A%09%09%09%09%09value = Integer.parseInt(string);%0D%0A%09%09%09%09%7D else if (!%22id%22.equals(property.getName()) %7C%7C property.getClazz() != Object.class) %7B%0D%0A%09
 %09%09%09%09Class%3C?%3E pro
@@ -2350,32 +2350,77 @@
 ty.getClazz();%0D%0A
+%09%09%09%09%09if (propertyClazz != String.class) %7B%0D%0A%09%09
 %09%09%09%09value = Fiel
@@ -2453,24 +2453,39 @@
 rtyClazz);%0D%0A
+%09%09%09%09%09%7D%0D%0A%09%09%09%09%7D%0D%0A
 %09%09%09%09property

support inputStream