
package cz.habarta.typescript.generator;

import java.lang.reflect.Type;
import java.util.*;
import java.util.logging.Logger;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.annotate.JsonSubTypes;
import org.codehaus.jackson.map.*;
import org.codehaus.jackson.map.ser.*;
import org.codehaus.jackson.type.JavaType;


public class Jackson1Parser extends ModelParser {

    private final ObjectMapper objectMapper = new ObjectMapper();

    public Jackson1Parser(Logger logger, Settings settings) {
        super(logger, settings);
    }

    @Override
    protected BeanModel parseBean(ClassWithUsage classWithUsage) {
        final BeanHelper beanHelper = getBeanHelper(classWithUsage.beanClass);
        final List<PropertyModel> properties = new ArrayList<>();
        for (BeanPropertyWriter beanPropertyWriter : beanHelper.getProperties()) {
            if (!isParentProperty(beanPropertyWriter.getName(), classWithUsage.beanClass)) {
                Type propertyType = beanPropertyWriter.getGenericPropertyType();
                if (propertyType.equals(JsonNode.class)) {
                    propertyType = Object.class;
                }
                properties.add(processTypeAndCreateProperty(beanPropertyWriter.getName(), propertyType, classWithUsage.beanClass));
            }
        }

        final JsonSubTypes jsonSubTypes = classWithUsage.beanClass.getAnnotation(JsonSubTypes.class);
        if (jsonSubTypes != null) {
            for (JsonSubTypes.Type type : jsonSubTypes.value()) {
                addBeanToQueue(new ClassWithUsage(type.value(), "<subClass>", classWithUsage.beanClass));
            }
        }
        final Class<?> superclass = classWithUsage.beanClass.getSuperclass().equals(Object.class) ? null : classWithUsage.beanClass.getSuperclass();
        if (superclass != null) {
            addBeanToQueue(new ClassWithUsage(superclass, "<superClass>", classWithUsage.beanClass));
        }
        return new BeanModel(getMappedName(classWithUsage.beanClass), getMappedName(superclass), properties);
    }

    private boolean isParentProperty(String property, Class<?> cls) {
        if (cls.getSuperclass().equals(Object.class)) {
            return false;
        } else {
            final BeanHelper beanHelper = getBeanHelper(cls.getSuperclass());
            for (BeanPropertyWriter beanPropertyWriter : beanHelper.getProperties()) {
                if (beanPropertyWriter.getName().equals(property)) {
                    return true;
                }
            }
            return false;
        }
    }

    private BeanHelper getBeanHelper(Class<?> beanClass) {
        try {
            final SerializationConfig serializationConfig = objectMapper.getSerializationConfig();
            final JavaType simpleType = objectMapper.constructType(beanClass);
            final JsonSerializer<?> jsonSerializer = BeanSerializerFactory.instance.createSerializer(serializationConfig, simpleType, null);
            if (jsonSerializer instanceof BeanSerializer) {
                return new BeanHelper((BeanSerializer) jsonSerializer);
            } else {
                final String jsonSerializerName = jsonSerializer != null ? jsonSerializer.getClass().getName() : null;
                throw new RuntimeException(String.format("Unknown serializer '%s' for class '%s'", jsonSerializerName, beanClass));
            }
        } catch (JsonMappingException e) {
            throw new RuntimeException(e);
        }
    }

    private static class BeanHelper extends BeanSerializer {

        public BeanHelper(BeanSerializer src) {
            super(src);
        }

        public BeanPropertyWriter[] getProperties() {
            return _props;
        }

    }

}

@@ -625,24 +625,90 @@
 ithUsage) %7B%0A
+        final List%3CPropertyModel%3E properties = new ArrayList%3C%3E();%0A
         fina
@@ -786,66 +786,38 @@
     
-final List%3CPropertyModel%3E properties = new ArrayList%3C%3E();%0A
+if (beanHelper != null) %7B%0A    
     
@@ -903,24 +903,28 @@
             
+    
 if (!isParen
@@ -1008,16 +1008,20 @@
         
+    
 Type pro
@@ -1089,24 +1089,28 @@
             
+   
+ 
 if (property
@@ -1132,32 +1132,36 @@
 nNode.class)) %7B%0A
+    
                 
@@ -1201,32 +1201,36 @@
                 
+    
 %7D%0A              
@@ -1227,24 +1227,28 @@
             
+ 
+   
 properties.a
@@ -1343,32 +1343,50 @@
 ge.beanClass));%0A
+                %7D%0A
             %7D%0A  
@@ -2383,24 +2383,66 @@
 erclass());%0A
+            if (beanHelper != null) %7B%0A    
             
@@ -2524,32 +2524,36 @@
                 
+   
+ 
 if (beanProperty
@@ -2605,24 +2605,28 @@
             
+    
 return true;
@@ -2626,16 +2626,38 @@
 n true;%0A
+                    %7D%0A
         
@@ -3115,16 +3115,101 @@
  null);%0A
+            if (jsonSerializer == null) %7B%0A                return null;%0A            %7D%0A
         

fix for empty classes