public class AbsListViewModelInfo extends AdapterViewModelInfo {

    interface Metadata {

        String CAN_SCROLL_LIST_DOWN = "can_scroll_list_down";

        String CAN_SCROLL_LIST_UP = "can_scroll_list_up";

        String CACHE_COLOR_HINT = "cache_color_hint";

        String CHECKED_ITEM_COUNT = "checked_item_count";

        String CHECKED_ITEM_POSITIONS = "checked_item_position";

        String CHOICE_MODE = "choice_mode";

        String LIST_PADDING_TOP = "list_padding_top";

        String LIST_PADDING_LEFT = "list_padding_left";

        String LIST_PADDING_BOTTOM = "list_padding_bottom";

        String LIST_PADDING_RIGHT = "list_padding_right";

        String SOLID_COLOR = "solid_color";

        String HAS_TEXT_FILTER = "has_text_filter";

        String FAST_SCROLL_ALWAYS_VISIBLE = "fast_scroll_always_visible";

        String SCROLLING_CACHE_ENABLED = "scrolling_cache_enabled";

        String SMOOTH_SCROLLBAR_ENABLED = "smooth_scrollbar_enabled";

        String STACK_FROM_BOTTOM = "stack_from_bottom";

        String TEXT_FILTER_ENABLED = "text_filter_enabled";
    }

    @SerializedName(Metadata.CAN_SCROLL_LIST_DOWN)
    boolean canScrollListDown;

    @SerializedName(Metadata.CAN_SCROLL_LIST_UP)
    boolean canScrollListUp;

    @SerializedName(Metadata.CACHE_COLOR_HINT)
    int cacheColorHint;

    @SerializedName(Metadata.CHECKED_ITEM_COUNT)
    int checkedItemCount;

    @SerializedName(Metadata.CHECKED_ITEM_POSITIONS)
    SparseBooleanArray checkedItemPositions;

    @SerializedName(Metadata.CHOICE_MODE)
    String choiceMode;

    @SerializedName(Metadata.LIST_PADDING_TOP)
    int listPaddingTop;

    @SerializedName(Metadata.LIST_PADDING_LEFT)
    int listPaddingLeft;

    @SerializedName(Metadata.LIST_PADDING_BOTTOM)
    int listPaddingBottom;

    @SerializedName(Metadata.LIST_PADDING_RIGHT)
    int listPaddingRight;

    @SerializedName(Metadata.SOLID_COLOR)
    int solidColor;

    @SerializedName(Metadata.HAS_TEXT_FILTER)
    boolean hasTextFilter;

    @SerializedName(Metadata.FAST_SCROLL_ALWAYS_VISIBLE)
    boolean fastScrollAlwaysVisible;

    @SerializedName(Metadata.SCROLLING_CACHE_ENABLED)
    boolean scrollingCacheEnabled;

    @SerializedName(Metadata.SMOOTH_SCROLLBAR_ENABLED)
    boolean smoothScrollbarEnabled;

    @SerializedName(Metadata.STACK_FROM_BOTTOM)
    boolean stackFromBottom;

    @SerializedName(Metadata.TEXT_FILTER_ENABLED)
    boolean textFilterEnabled;

    private transient SparseArray<String> choiceModeToStringMap = new SparseArray<String>(4) {
        {
            put(AbsListView.CHOICE_MODE_NONE, "CHOICE_MODE_NONE");
            put(AbsListView.CHOICE_MODE_SINGLE, "CHOICE_MODE_SINGLE");
            put(AbsListView.CHOICE_MODE_MULTIPLE, "CHOICE_MODE_MULTIPLE");
            put(AbsListView.CHOICE_MODE_MULTIPLE_MODAL, "CHOICE_MODE_MULTIPLE_MODAL");
        }
    };

    @Override
    public void setDataFromView(View view, ConvertersContainer convertersContainer) {
        super.setDataFromView(view, convertersContainer);

        AbsListView absListView = (AbsListView) view;
        if (android.os.Build.VERSION.SDK_INT >= 19) {
            canScrollListDown = absListView.canScrollList(1);
            canScrollListUp = absListView.canScrollList(-1);
        }
        cacheColorHint = absListView.getCacheColorHint();
        checkedItemCount = absListView.getCheckedItemCount();
        checkedItemPositions = absListView.getCheckedItemPositions();
        choiceMode = choiceModeToStringMap.get(absListView.getChoiceMode());
        listPaddingTop = absListView.getListPaddingTop();
        listPaddingLeft = absListView.getListPaddingLeft();
        listPaddingBottom = absListView.getListPaddingBottom();
        listPaddingRight = absListView.getListPaddingRight();
        solidColor = absListView.getSolidColor();
        hasTextFilter = absListView.hasTextFilter();
        fastScrollAlwaysVisible = absListView.isFastScrollAlwaysVisible();
        scrollingCacheEnabled = absListView.isScrollingCacheEnabled();
        smoothScrollbarEnabled = absListView.isSmoothScrollbarEnabled();
        stackFromBottom = absListView.isStackFromBottom();
        textFilterEnabled = absListView.isTextFilterEnabled();
    }
} public class AbsSpinnerModelInfo extends AdapterViewModelInfo {

} public class AdapterViewAnimatorModelInfo extends AdapterViewModelInfo {

    interface Metadata {

        String DISPLAYED_CHILD = "displayed_child";
    }

    @SerializedName(Metadata.DISPLAYED_CHILD)
    int displayedChild;

    @Override
    public void setDataFromView(View view, ConvertersContainer convertersContainer) {
        super.setDataFromView(view, convertersContainer);

        AdapterViewAnimator adapterViewAnimator = (AdapterViewAnimator) view;
        displayedChild = adapterViewAnimator.getDisplayedChild();
    }
} public class AdapterViewFlipperModelInfo extends AdapterViewAnimatorModelInfo {

    interface Metadata {

        String FLIP_INTERVAL = "flip_interval";

        String IS_AUTO_START = "is_auto_start";
    }

    @SerializedName(Metadata.FLIP_INTERVAL)
    int flipInterval;

    @SerializedName(Metadata.IS_AUTO_START)
    boolean isAutoStart;

    @Override
    public void setDataFromView(View view, ConvertersContainer convertersContainer) {
        super.setDataFromView(view, convertersContainer);

        AdapterViewFlipper flipper = (AdapterViewFlipper) view;
        if (android.os.Build.VERSION.SDK_INT >= 16) {
            flipInterval = flipper.getFlipInterval();
        }
        isAutoStart = flipper.isAutoStart();
    }
} public class AdapterViewModelInfo extends ViewGroupModelInfo {

    interface Metadata {

        String ITEM_COUNT = "item_count";

        String SELECTED_ITEM_POSITION = "selected_item_position";

        String SELECTED_ITEM_ID = "selected_item_id";

        String FIRST_VISIBLE_POSITION = "first_visible_position";

        String LAST_VISIBLE_POSITION = "last_visible_position";

        String ADAPTER_VIEW_TYPE_COUNT = "adapter_view_type_count";
    }

    @SerializedName(Metadata.ITEM_COUNT)
    int itemCount;

    @SerializedName(Metadata.SELECTED_ITEM_POSITION)
    int selectedItemPosition;

    @SerializedName(Metadata.SELECTED_ITEM_ID)
    long selectedItemId;

    @SerializedName(Metadata.FIRST_VISIBLE_POSITION)
    int firstVisiblePosition;

    @SerializedName(Metadata.LAST_VISIBLE_POSITION)
    int lastVisiblePosition;

    @SerializedName(Metadata.ADAPTER_VIEW_TYPE_COUNT)
    int adapterViewTypeCount;


    @Override
    public void setDataFromView(View view, ConvertersContainer convertersContainer) {
        super.setDataFromView(view, convertersContainer);

        AdapterView adapterView = (AdapterView) view;
        itemCount = adapterView.getCount();
        selectedItemPosition = adapterView.getSelectedItemPosition();
        selectedItemId = adapterView.getSelectedItemId();
        firstVisiblePosition = adapterView.getFirstVisiblePosition();
        lastVisiblePosition = adapterView.getLastVisiblePosition();
        Adapter adapter = adapterView.getAdapter();
        if(adapter != null) {
            adapterViewTypeCount = adapter.getViewTypeCount();
        }
    }
} public class ButtonModelInfo extends TextViewModelInfo {

} public class CheckBoxModelInfo extends CompoundButtonModelInfo{

} public class CheckedTextViewModelInfo extends TextViewModelInfo {

    public interface Metadata {

        String IS_CHECKED = "isChecked";
    }

    @SerializedName(Metadata.IS_CHECKED)
    boolean isChecked;

    @Override
    public void setDataFromView(View view, ConvertersContainer convertersContainer) {
        super.setDataFromView(view, convertersContainer);
        CheckedTextView checkedTextView = (CheckedTextView) view;
        isChecked = checkedTextView.isChecked();
    }
} public class CompoundButtonModelInfo extends ButtonModelInfo {

    public interface Metadata {

        String IS_CHECKED = "is_checked";
    }

    @SerializedName(Metadata.IS_CHECKED)
    boolean isChecked;

    @Override
    public void setDataFromView(View view, ConvertersContainer convertersContainer) {
        super.setDataFromView(view, convertersContainer);
        CompoundButton compoundButton = (CompoundButton) view;
        isChecked = compoundButton.isChecked();
    }
} public class ExpandableListViewModelInfo extends ListViewModelInfo {

    interface Metadata {

        String SELECTED_ID = "selected_id";

        String SELECTED_POSITION = "selected_position";
    }

    @SerializedName(Metadata.SELECTED_ID)
    long selectedId;

    @SerializedName(Metadata.SELECTED_POSITION)
    long selectedPosition;

    @Override
    public void setDataFromView(View view, ConvertersContainer convertersContainer) {
        super.setDataFromView(view, convertersContainer);

        ExpandableListView expandableListView = (ExpandableListView) view;
        selectedId = expandableListView.getSelectedId();
        selectedPosition = expandableListView.getSelectedPosition();
    }
} public class GridLayoutModelInfo extends ViewGroupModelInfo {

    interface Metadata {
        String COLUMN_COUNT = "column_count";
        String ROW_COUNT = "row_count";
        String IS_COLUMN_ORDER_PRESERVED = "is_column_order_preserved";
        String IS_ROW_ORDER_RESERVED = "is_row_order_preserved";
        String ALIGNMENT_MODE = "alignment_mode";
    }

    @SerializedName(Metadata.COLUMN_COUNT)
    int columnCount;

    @SerializedName(Metadata.ROW_COUNT)
    int rowCount;

    @SerializedName(Metadata.IS_COLUMN_ORDER_PRESERVED)
    boolean isColumnOrderPreserved;

    @SerializedName(Metadata.IS_ROW_ORDER_RESERVED)
    boolean isRowOrderPreserved;

    @SerializedName(Metadata.ALIGNMENT_MODE)
    AlignmentMode alignmentMode;

    @Override
    public void setDataFromView(View view, ConvertersContainer convertersContainer) {
        super.setDataFromView(view, convertersContainer);
        GridLayout gridLayout = (GridLayout) view;
        columnCount = gridLayout.getColumnCount();
        rowCount = gridLayout.getRowCount();
        isColumnOrderPreserved = gridLayout.isColumnOrderPreserved();
        isRowOrderPreserved = gridLayout.isRowOrderPreserved();
        alignmentMode = AlignmentMode.getAlignmentMode(gridLayout.getAlignmentMode());
    }
} public class GridViewModelInfo extends AbsListViewModelInfo {

    interface Metadata {

        String COLUMN_WIDTH = "column_width";

        String GRAVITY = "gravity";

        String HORIZONTAL_SPACING = "horizontal_spacing";

        String NUM_COLUMNS = "num_columns";

        String REQUESTED_COLUMN_WIDTH = "requested_column_width";

        String REQUESTED_HORIZONTAL_SPACING = "requested_horizontal_spacing";

        String STRETCH_MODE = "stretch_mode";

        String VERTICAL_SPACING = "vertical_spacing";
    }

    @SerializedName(Metadata.COLUMN_WIDTH)
    int columnWidth;

    @SerializedName(Metadata.GRAVITY)
    int gravity;

    @SerializedName(Metadata.HORIZONTAL_SPACING)
    int horizontalSpacing;

    @SerializedName(Metadata.NUM_COLUMNS)
    int numColumns;

    @SerializedName(Metadata.REQUESTED_COLUMN_WIDTH)
    int requestedColumnWidth;

    @SerializedName(Metadata.REQUESTED_HORIZONTAL_SPACING)
    int requestedHorizontalSpacing;

    @SerializedName(Metadata.STRETCH_MODE)
    String stretchMode;

    @SerializedName(Metadata.VERTICAL_SPACING)
    int verticalSpacing;

    private transient SparseArray<String> stretchModeToStringMap = new SparseArray<String>(4) {
        {
            put(GridView.NO_STRETCH, "NO_STRETCH");
            put(GridView.STRETCH_SPACING, "STRETCH_SPACING");
            put(GridView.STRETCH_COLUMN_WIDTH, "STRETCH_COLUMN_WIDTH");
            put(GridView.STRETCH_SPACING_UNIFORM, "STRETCH_SPACING_UNIFORM");
        }
    };

    @Override
    public void setDataFromView(View view, ConvertersContainer convertersContainer) {
        super.setDataFromView(view, convertersContainer);

        GridView gridView = (GridView) view;
        if (android.os.Build.VERSION.SDK_INT >= 16) {
            columnWidth = gridView.getColumnWidth();
            gravity = gridView.getGravity();
            horizontalSpacing = gridView.getHorizontalSpacing();
            requestedColumnWidth = gridView.getRequestedColumnWidth();
            requestedHorizontalSpacing = gridView.getRequestedHorizontalSpacing();
            verticalSpacing = gridView.getVerticalSpacing();
        }
        numColumns = gridView.getNumColumns();
        stretchMode = stretchModeToStringMap.get(gridView.getStretchMode());
    }
} public class ImageViewModelInfo extends ViewModelInfo {

    interface Metadata {

        String SCALE_TYPE = "scale_type";

        String BITMAP_WIDTH = "bitmap_width";
        String BITMAP_HEIGHT = "bitmap_height";
    }

    @SerializedName(Metadata.SCALE_TYPE)
    ImageView.ScaleType scaleType;


    @SerializedName(Metadata.BITMAP_WIDTH)
    Integer bitmapImageWidth;

    @SerializedName(Metadata.BITMAP_HEIGHT)
    Integer bitmapImageHeight;

    @Override
    public void setDataFromView(View view, ConvertersContainer convertersContainer) {
        super.setDataFromView(view, convertersContainer);
        final ImageView imageView = (ImageView) view;
        scaleType = imageView.getScaleType();

        final Drawable drawable = imageView.getDrawable();

        if (drawable instanceof BitmapDrawable) {
            final BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
            final Bitmap bmp = bitmapDrawable.getBitmap();
            if (bmp != null) {
                bitmapImageWidth = bmp.getWidth();
                bitmapImageHeight = bmp.getHeight();
            }
        }
    }
} public class ListViewModelInfo extends AbsListViewModelInfo {

    interface Metadata {

        String ARE_HEADER_DIVIDERS_ENABLED = "are_header_dividers_enabled";

        String ARE_FOOTER_DIVIDERS_ENABLED = "are_footer_dividers_enabled";

        String DIVIDER_HEIGHT = "divider_height";

        String FOOTER_VIEWS_COUNT = "footer_views_count";

        String HEADER_VIEWS_COUNT = "header_views_count";

        String ITEMS_CAN_FOCUS = "items_can_focus";

        String MAX_SCROLL_AMOUNT = "max_scroll_amount";
    }

    @SerializedName(Metadata.ARE_HEADER_DIVIDERS_ENABLED)
    boolean areHeaderDividersEnabled;

    @SerializedName(Metadata.ARE_FOOTER_DIVIDERS_ENABLED)
    boolean areFooterDividersEnabled;

    @SerializedName(Metadata.DIVIDER_HEIGHT)
    int dividerHeight;

    @SerializedName(Metadata.FOOTER_VIEWS_COUNT)
    int footerViewsCount;

    @SerializedName(Metadata.HEADER_VIEWS_COUNT)
    int headerViewsCount;

    @SerializedName(Metadata.ITEMS_CAN_FOCUS)
    boolean itemsCanFocus;

    @SerializedName(Metadata.MAX_SCROLL_AMOUNT)
    int maxScrollAmount;

    @Override
    public void setDataFromView(View view, ConvertersContainer convertersContainer) {
        super.setDataFromView(view, convertersContainer);

        ListView listView = (ListView) view;
        if (android.os.Build.VERSION.SDK_INT >= 19) {
            areHeaderDividersEnabled = listView.areHeaderDividersEnabled();
            areFooterDividersEnabled = listView.areFooterDividersEnabled();
        }

        dividerHeight = listView.getDividerHeight();
        footerViewsCount = listView.getFooterViewsCount();
        headerViewsCount = listView.getHeaderViewsCount();
        itemsCanFocus = listView.getItemsCanFocus();
        maxScrollAmount = listView.getMaxScrollAmount();
    }
} public interface ModelInfo {

    int ID_NOT_FOUND = -1;

    void setDataFromView(View view, ConvertersContainer convertersContainer);
} public class ProgressBarModelInfo extends ViewModelInfo {

    interface Metadata {

        String MAX = "max";
        String PROGRESS = "progress";
        String SECONDARY_PROGRESS = "secondary_progress";
    }

    @SerializedName(Metadata.MAX)
    int max;

    @SerializedName(Metadata.PROGRESS)
    int progress;

    @SerializedName(Metadata.SECONDARY_PROGRESS)
    int secondaryProgress;

    @Override
    public void setDataFromView(View view, ConvertersContainer convertersContainer) {
        super.setDataFromView(view, convertersContainer);
        ProgressBar progressBar = (ProgressBar) view;
        max = progressBar.getMax();
        progress = progressBar.getProgress();
        secondaryProgress = progressBar.getSecondaryProgress();
    }
} public class RadioButtonModelInfo extends CompoundButtonModelInfo {

} public class RadioGroupModelInfo extends ViewGroupModelInfo {

    interface Metadata{
        String CHECKED_ITEM_ID = "checked_item_id";
    }

    @SerializedName(Metadata.CHECKED_ITEM_ID)
    int checkedItemId;

    @Override
    public void setDataFromView(View view, ConvertersContainer convertersContainer) {
        super.setDataFromView(view, convertersContainer);
        final RadioGroup radioGroup = (RadioGroup) view;
        checkedItemId = radioGroup.getCheckedRadioButtonId();
    }
} public class RatingBarModelInfo extends AbsSeekBarModelInfo {

    interface Metadata {

        String RATING = "rating";
        String STEP_SIZE = "step_size";
        String NUM_STAR = "numStar";
        String IS_INDICATOR = "is_indicator";
    }

    @SerializedName(Metadata.RATING)
    float rating;

    @SerializedName(Metadata.STEP_SIZE)
    float stepSize;

    @SerializedName(Metadata.NUM_STAR)
    int numStar;

    @SerializedName(Metadata.IS_INDICATOR)
    boolean isIndicator;


    @Override
    public void setDataFromView(View view, ConvertersContainer convertersContainer) {
        super.setDataFromView(view, convertersContainer);
        RatingBar ratingBar = (RatingBar) view;
        rating = ratingBar.getRating();
        stepSize = ratingBar.getStepSize();
        numStar = ratingBar.getNumStars();
        isIndicator = ratingBar.isIndicator();
    }
} public class RecyclerViewModelInfo extends ViewGroupModelInfo {

    interface Metadata {

        String HAS_FIXED_SIZE = "has_fixed_size";

        String CAN_SCROLL_HORIZONTALLY = "can_scroll_horizontally";

        String CAN_SCROLL_VERTICALLY = "can_scroll_vertically";

        String ITEM_COUNT = "item_count";

        String SMOOTH_SCROLLING = "smooth_scrolling";

        String SUPPORT_PREDICTIVE_ITEM_ANIMATIONS = "support_predictive_item_animations";

        String LAYOUT_MANAGER_CLASS_NAME = "layout_manager_class_name";
    }

    @SerializedName(Metadata.LAYOUT_MANAGER_CLASS_NAME)
    String layoutManagerClassName;

    @SerializedName(Metadata.HAS_FIXED_SIZE)
    boolean hasFixedSize;

    @SerializedName(Metadata.CAN_SCROLL_HORIZONTALLY)
    boolean canScrollHorizontally;

    @SerializedName(Metadata.CAN_SCROLL_VERTICALLY)
    boolean canScrollVertically;

    @SerializedName(Metadata.ITEM_COUNT)
    int itemCount;

    @SerializedName(Metadata.SMOOTH_SCROLLING)
    boolean smoothScrolling;

    @SerializedName(Metadata.SUPPORT_PREDICTIVE_ITEM_ANIMATIONS)
    boolean supportsPredictiveItemAnimations;

    @Override
    public void setDataFromView(View view, ConvertersContainer convertersContainer) {
        super.setDataFromView(view, convertersContainer);

        RecyclerView recyclerView = (RecyclerView) view;
        hasFixedSize = recyclerView.hasFixedSize();
        RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();
        if (layoutManager != null) {
            layoutManagerClassName = layoutManager.getClass().getSimpleName();
            canScrollHorizontally = layoutManager.canScrollHorizontally();
            canScrollVertically = layoutManager.canScrollVertically();
            itemCount = layoutManager.getItemCount();
            smoothScrolling = layoutManager.isSmoothScrolling();
            supportsPredictiveItemAnimations = layoutManager.supportsPredictiveItemAnimations();
        }
    }
} public class SpinnerModelInfo extends AbsSpinnerModelInfo {

    interface Metadata {

        String GRAVITY = "gravity";

        String DROP_DOWN_HORIZONTAL_OFFSET = "drop_down_horizontal_offset";

        String DROP_DOWN_VERTICAL_OFFSET = "drop_down_vertical_offset";

        String DROP_DOWN_WIDTH = "drop_down_width";

        String PROMPT = "prompt";
    }

    @SerializedName(Metadata.GRAVITY)
    int gravity;

    @SerializedName(Metadata.DROP_DOWN_HORIZONTAL_OFFSET)
    int dropDownHorizontalOffset;

    @SerializedName(Metadata.DROP_DOWN_VERTICAL_OFFSET)
    int dropDownVerticalOffset;

    @SerializedName(Metadata.DROP_DOWN_WIDTH)
    int dropDownWidth;

    @SerializedName(Metadata.PROMPT)
    String prompt;

    @Override
    public void setDataFromView(View view, ConvertersContainer convertersContainer) {
        super.setDataFromView(view, convertersContainer);

        Spinner spinner = (Spinner) view;

        if (android.os.Build.VERSION.SDK_INT >= 16) {
            dropDownHorizontalOffset = spinner.getDropDownHorizontalOffset();
            dropDownVerticalOffset = spinner.getDropDownVerticalOffset();
            dropDownWidth = spinner.getDropDownWidth();
            gravity = spinner.getGravity();
        }

        CharSequence prompt = spinner.getPrompt();
        if(prompt != null) {
            this.prompt = prompt.toString();
        }
    }
} public class SwitchModelInfo extends CompoundButtonModelInfo {

} public class TextViewModelInfo extends ViewModelInfo {
    interface Metadata {
        String TEXT = "text";
    }

    @SerializedName(Metadata.TEXT)
    String text;

    @Override
    public void setDataFromView(View view, ConvertersContainer convertersContainer) {
        super.setDataFromView(view, convertersContainer);
        TextView textView = (TextView) view;
        text = textView.getText().toString();
    }
} public class ToggleButtonModelInfo extends CompoundButtonModelInfo {

} public class ViewGroupModelInfo extends ViewModelInfo {

    interface Metadata {

        String CHILDREN = "children";
        String COUNT_CHILDREN = "count_children";
    }

    @SerializedName(Metadata.COUNT_CHILDREN)
    int countChildren;

    @SerializedName(Metadata.CHILDREN)
    List<ModelInfo> children;

    @Override
    public void setDataFromView(View view, ConvertersContainer convertersContainer) {
        super.setDataFromView(view, convertersContainer);
        ViewGroup viewGroup = (ViewGroup) view;
        countChildren = viewGroup.getChildCount();
        if (countChildren > 0) {
            children = new LinkedList<>();
        }
        for (int index = 0; index < countChildren; index++) {
            View child = viewGroup.getChildAt(index);
            final ModelInfo viewModelInfo = convertersContainer.getModelInfoForClass(child.getClass());
            viewModelInfo.setDataFromView(child, convertersContainer);
            children.add(viewModelInfo);
        }
    }
} public class ViewModelInfo implements ModelInfo {

    interface Metadata {

        String PACKAGE_NAME = "package_name";

        String NAME = "name";
        String ID = "id";
        String ID_RES_NAME = "id_res_name";
        String GENERATE_ID = "generate_id";
        String ENABLED = "enabled";
        String VISIBILITY = "visibility";
        String X = "x";
        String Y = "y";
        String SCROLL_X = "scroll_x";
        String SCROLL_Y = "scroll_y";
        String SCALE_X = "scale_x";
        String SCALE_Y = "scale_y";

        String WIDTH = "width";
        String HEIGHT = "height";
        String PATH_TO_FILE = "path_to_file";

        String LAYOUT_PARAM = "layout_param";

        String ALPHA = "alpha";

    }

    @SerializedName(Metadata.PACKAGE_NAME)
    String packageName;

    @SerializedName(Metadata.NAME)
    String name;

    @SerializedName(Metadata.ID)
    int id;

    @SerializedName(Metadata.ID_RES_NAME)
    String idResName;

    @SerializedName(Metadata.GENERATE_ID)
    long generateId;

    @SerializedName(Metadata.ENABLED)
    boolean enabled;

    @SerializedName(Metadata.VISIBILITY)
    Visibility visibility;

    @SerializedName(Metadata.X)
    float x;

    @SerializedName(Metadata.Y)
    float y;

    @SerializedName(Metadata.WIDTH)
    float width;

    @SerializedName(Metadata.HEIGHT)
    float height;

    @SerializedName(Metadata.PATH_TO_FILE)
    String pathToFile;

    @SerializedName(Metadata.ALPHA)
    float alpha;

    @SerializedName(Metadata.LAYOUT_PARAM)
    LayoutParamsModelInfo layoutParamModelInfo;

    @SerializedName(Metadata.SCROLL_X)
    int scrollX;

    @SerializedName(Metadata.SCROLL_Y)
    int scrollY;

    @SerializedName(Metadata.SCALE_X)
    float scaleX;

    @SerializedName(Metadata.SCALE_Y)
    float scaleY;

    @Override
    public void setDataFromView(View view, ConvertersContainer convertersContainer) {
        packageName = view.getClass().getPackage().getName();
        generateId = UUID.randomUUID().getMostSignificantBits();
        name = view.getClass().getSimpleName();
        id = view.getId();
        if (id != ID_NOT_FOUND) {
            try {
                idResName = view.getContext().getResources().getResourceEntryName(id);
            } catch (Resources.NotFoundException ignored) {}
        }

        enabled = view.isEnabled();
        visibility = Visibility.getFromViewVisibility(view.getVisibility());

        width = view.getWidth();
        height = view.getHeight();

        Pair<Float, Float> point = calculateLocation(view);
        x = point.first;
        y = point.second;

        scrollX = view.getScrollX();
        scrollY = view.getScrollY();

        scaleX = view.getScaleX();
        scaleY = view.getScaleY();

        ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
        if (layoutParams != null) {
            layoutParamModelInfo = convertersContainer.getLayoutParamsModelInfo(layoutParams.getClass());
            layoutParamModelInfo.setDataFromLayoutParams(layoutParams);
        }
        alpha = view.getAlpha();
    }

    private Pair<Float, Float> calculateLocation(View view) {
        ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
        if (layoutParams.getClass() == WindowManager.LayoutParams.class) {
            return calculateRootViewLocation(view, (WindowManager.LayoutParams) layoutParams);
        }
        return new Pair<>(view.getX(), view.getY());
    }

    private Pair<Float, Float> calculateRootViewLocation(View view, WindowManager.LayoutParams windowLayoutParams) {
        float x = view.getX();
        float y = view.getY();
        if (windowLayoutParams.width != ViewGroup.LayoutParams.MATCH_PARENT && windowLayoutParams.height != ViewGroup.LayoutParams.MATCH_PARENT) {
            try {
                ViewParent parent = view.getParent();
                Field winFrameField = parent.getClass().getDeclaredField("mWinFrame");
                winFrameField.setAccessible(true);
                Rect rect = (Rect) winFrameField.get(parent);
                x = rect.left;
                y = rect.top;
            } catch (Exception ignored) {

            }
        }
        return new Pair<>(x, y);
    }

    public void setPathToFile(String pathToFile) {
        this.pathToFile = pathToFile;
    }
}
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AbsSpinner;
import android.widget.AdapterView;
import android.widget.AdapterViewAnimator;
import android.widget.AdapterViewFlipper;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CheckedTextView;
import android.widget.CompoundButton;
import android.widget.ExpandableListView;
import android.widget.GridLayout;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.RatingBar;
import android.widget.Spinner;
import android.widget.Switch;
import android.widget.TextView;
import android.widget.ToggleButton;
import com.polidea.hierarchyviewer.internal.model.view.AbsListViewModelInfo;
import com.polidea.hierarchyviewer.internal.model.view.AbsSpinnerModelInfo;
import com.polidea.hierarchyviewer.internal.model.view.AdapterViewAnimatorModelInfo;
import com.polidea.hierarchyviewer.internal.model.view.AdapterViewFlipperModelInfo;
import com.polidea.hierarchyviewer.internal.model.view.AdapterViewModelInfo;
import com.polidea.hierarchyviewer.internal.model.view.ButtonModelInfo;
import com.polidea.hierarchyviewer.internal.model.view.CheckBoxModelInfo;
import com.polidea.hierarchyviewer.internal.model.view.CheckedTextViewModelInfo;
import com.polidea.hierarchyviewer.internal.model.view.CompoundButtonModelInfo;
import com.polidea.hierarchyviewer.internal.model.view.ExpandableListViewModelInfo;
import com.polidea.hierarchyviewer.internal.model.view.GridLayoutModelInfo;
import com.polidea.hierarchyviewer.internal.model.view.GridViewModelInfo;
import com.polidea.hierarchyviewer.internal.model.view.ImageViewModelInfo;
import com.polidea.hierarchyviewer.internal.model.view.ListViewModelInfo;
import com.polidea.hierarchyviewer.internal.model.view.ModelInfo;
import com.polidea.hierarchyviewer.internal.model.view.ProgressBarModelInfo;
import com.polidea.hierarchyviewer.internal.model.view.RadioButtonModelInfo;
import com.polidea.hierarchyviewer.internal.model.view.RadioGroupModelInfo;
import com.polidea.hierarchyviewer.internal.model.view.RatingBarModelInfo;
import com.polidea.hierarchyviewer.internal.model.view.RecyclerViewModelInfo;
import com.polidea.hierarchyviewer.internal.model.view.SpinnerModelInfo;
import com.polidea.hierarchyviewer.internal.model.view.SwitchModelInfo;
import com.polidea.hierarchyviewer.internal.model.view.TextViewModelInfo;
import com.polidea.hierarchyviewer.internal.model.view.ToggleButtonModelInfo;
import com.polidea.hierarchyviewer.internal.model.view.ViewGroupModelInfo;
import com.polidea.hierarchyviewer.internal.model.view.ViewModelInfo;
package com.polidea.hierarchyviewer.internal.logic;


public enum SystemViewConverter implements ViewConverter {

    GRID_LAYOUT(GridLayout.class) {
        @Override
        public GridLayoutModelInfo getModelInfo() {
            return new GridLayoutModelInfo();
        }
    },
    RADIO_GROUP(RadioGroup.class) {
        @Override
        public RadioGroupModelInfo getModelInfo() {
            return new RadioGroupModelInfo();
        }
    },
    RATING_BAR(RatingBar.class) {
        @Override
        public RatingBarModelInfo getModelInfo() {
            return new RatingBarModelInfo();
        }
    },

    TOGGLE_BUTTON(ToggleButton.class) {
        @Override
        public ToggleButtonModelInfo getModelInfo() {
            return new ToggleButtonModelInfo();
        }
    },

    SWITCH(Switch.class) {
        @Override
        public SwitchModelInfo getModelInfo() {