package io.subutai.common.gson.required;


import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.util.Collection;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.apache.cxf.common.util.CollectionUtils;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.reflect.TypeToken;

import io.subutai.common.environment.Node;


public class RequiredDeserializer<T> implements JsonDeserializer<T>
{
    private static final Logger LOG = LoggerFactory.getLogger( RequiredDeserializer.class );


    @Override
    public T deserialize( final JsonElement jsonElement, final Type type,
                          final JsonDeserializationContext jsonDeserializationContext ) throws JsonParseException
    {
        T object = new Gson().fromJson( jsonElement, type );

        Field[] fields = object.getClass().getDeclaredFields();

        for ( Field field : fields )
        {
            validate( field, object );
        }

        return object;
    }


    private void validate( Field field, T object )
    {
        if ( field.getAnnotation( GsonRequired.class ) != null )
        {
            try
            {
                field.setAccessible( true );

                switch ( field.getAnnotation( GsonRequired.class ).validation() )
                {
                    case GREATER_THAN_ZERO:
                        try
                        {
                            if ( field.get( object ) == null
                                    && Integer.parseInt( ( String ) field.get( object ) ) <= 0 )
                            {
                                throw new JsonParseException(
                                        "Json validation failed expected x > field: " + field.getName() );
                            }
                        }
                        catch ( Exception e )
                        {
                            throw new JsonParseException(
                                    "Json parse error, expected int for the field: " + field.getName() );
                        }

                        break;
                    default:

                        if ( CollectionUtils.isEmpty( ( Collection ) field.get( object ) ) )
                        {
                            throw new JsonParseException( "Missing Json field: " + field.getName() );
                        }

                        if ( field.get( object ) instanceof Collection<?> )
                        {
                            Gson gson = RequiredDeserializer.createValidatingGson();

                            gson.fromJson( new Gson().toJson( field.get( object ) ), new TypeToken<Collection<?>>()
                            {
                            }.getType() );
                        }
                }
            }
            catch ( IllegalAccessException | IllegalArgumentException e )
            {
                LOG.error( "Deserialization error", e );
            }
        }
    }


    public static Gson createValidatingGson()
    {
        return new GsonBuilder().registerTypeAdapter( Node.class, new RequiredDeserializer<Node>() ).setPrettyPrinting()
                                .create();
    }
}

@@ -1571,195 +1571,46 @@
     
-try%0A                        %7B%0A                            if ( field.get( object ) == null%0A                                    && Integer.parseInt( ( String ) field.get( object ) ) %3C= 0 )
+checkGreaterThanZero( field, object );
 %0A   
@@ -1622,37 +1622,38 @@
                 
-    %7B
+break;
 %0A               
@@ -1661,332 +1661,167 @@
     
-            throw new JsonParseException(%0A                                        %22Json validation failed expected x %3E field: %22 + field.getName() );%0A                            %7D%0A                        %7D%0A                        catch ( Exception e )%0A                        %7B%0A                            throw new JsonParse
+default:%0A                        checkCollection( field, object );%0A                %7D%0A            %7D%0A            catch ( IllegalAccessException %7C IllegalArgument
 Exce
@@ -1829,11 +1829,13 @@
 tion
-(%0A 
+ e )%0A
     
@@ -1834,38 +1834,34 @@
 e )%0A            
-      
+%7B%0A
                 
@@ -1864,75 +1864,45 @@
     
- %22Json parse error, expected int for the field: %22 + field.getName()
+LOG.error( %22Deserialization error%22, e
  );%0A
@@ -1905,36 +1905,34 @@
  );%0A            
-    
+%7D%0A
         %7D%0A%0A     
@@ -1929,86 +1929,110 @@
   %7D%0A
-%0A                        break;%0A                    default:%0A%0A                
+    %7D%0A%0A%0A    private void checkCollection( Field field, T object ) throws IllegalAccessException%0A    %7B%0A
     
@@ -2104,32 +2104,16 @@
 t ) ) )%0A
-                
         
@@ -2114,32 +2114,16 @@
       %7B%0A
-                
         
@@ -2212,43 +2212,11 @@
     
-                %7D%0A%0A                
+%7D%0A%0A
     
@@ -2283,36 +2283,10 @@
     
-                %7B%0A          
+%7B%0A
     
@@ -2293,22 +2293,16 @@
         
-      
 Gson gso
@@ -2351,32 +2351,16 @@
 son();%0A%0A
-                
         
@@ -2455,32 +2455,34 @@
 %3E()%0A            
+%7B%0A
                 
@@ -2481,68 +2481,130 @@
     
- 
+%7D.getType() );%0A
    
-%7B%0A
      
+%7D%0A
     
-           
+%7D%0A%0A%0A    private void checkGreaterThanZero( Field field, T object )%0A
     
+%7B%0A
     
-%7D.getType() );%0A   
+    try%0A
         
     
@@ -2591,32 +2591,34 @@
     try%0A        
+%7B%0A
              %7D%0A 
@@ -2617,28 +2617,101 @@
     
- %7D%0A                %7D
+if ( field.get( object ) == null %7C%7C Integer.parseInt( ( String ) field.get( object ) ) %3C= 0 )
 %0A   
@@ -2711,34 +2711,35 @@
 0 )%0A            
-%7D%0A
+%7B%0A 
             catc
@@ -2738,56 +2738,148 @@
     
-catch ( IllegalAccessException %7C IllegalArgument
+   throw new JsonParseException( %22Json validation failed expected x %3E field: %22 + field.getName() );%0A            %7D%0A        %7D%0A        catch ( 
 Exce
@@ -2880,36 +2880,32 @@
 ( Exception e )%0A
-    
         %7B%0A      
@@ -2914,66 +2914,107 @@
     
-    LOG.error( %22Deserialization
+throw new JsonParseException( %22Json parse
  error
-%22
 , e
- );%0A            %7D
+xpected int for the field: %22 + field.getName() );
 %0A   

switch case refactor