/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.ignite.yardstick.cache.load.model;

import java.util.UUID;
import org.apache.ignite.yardstick.cache.load.model.key.Identifier;
import org.apache.ignite.yardstick.cache.load.model.key.Mark;
import org.apache.ignite.yardstick.cache.load.model.value.Car;
import org.apache.ignite.yardstick.cache.load.model.value.Color;
import org.apache.ignite.yardstick.cache.load.model.value.Truck;
import org.apache.ignite.yardstick.cache.model.Account;
import org.apache.ignite.yardstick.cache.model.Organization;
import org.apache.ignite.yardstick.cache.model.Person;
import org.apache.ignite.yardstick.cache.model.Person1;
import org.apache.ignite.yardstick.cache.model.Person2;
import org.apache.ignite.yardstick.cache.model.Person8;

/**
 * Util class for model.
 */
public class ModelUtil {
    /**
     * Classes of keys.
     */
    private static Class[] keyClasses = {
        Double.class,
        Identifier.class,
        Mark.class,
        Integer.class,
        UUID.class,
        String.class
    };

    /**
     * Classes of values.
     */
    private static Class[] valClasses = {
//        Car.class,
//        Truck.class,
        Person.class,
        Organization.class,
        Account.class,
        Person1.class,
        Person2.class,
        Person8.class
    };

    /**
     * @param clazz Checked class.
     * @return Result.
     */
    public static boolean canCreateInstance(Class clazz) {
        for (Class c: keyClasses) {
            if (c.equals(clazz))
                return true;
        }

        for (Class c: valClasses) {
            if (c.equals(clazz))
                return true;
        }

        return false;
    }

    /**
     * @param c model class
     * @param id object id
     * @return object from model
     */
    public static Object create(Class c, int id) {
        Object res = null;

        switch (c.getSimpleName()) {
            case "Double":
                res = Double.valueOf(id);
                break;
            case "Identifier":
                res = new Identifier(id, "id " + id);
                break;
            case "Mark":
                res = new Mark(id, UUID.nameUUIDFromBytes(Integer.toString(id).getBytes()));
                break;
            case "Integer":
                res = id;
                break;
            case "UUID":
                res = UUID.nameUUIDFromBytes(Integer.toString(id).getBytes());
                break;
            case "Car":
                int colorCnt = Color.values().length;
                res = new Car(id, "Mark " + id, id / 2.123 * 100, Color.values()[id % colorCnt]);
                break;
            case "Truck":
                int colors = Color.values().length;
                res = new Truck(id, "Mark " + id, id / 2.123 * 100, Color.values()[id % colors], id / 4.123 * 100);
                break;
            case "Person":
                res = new Person(id, id+1, "First Name " + id, "Last Name " + id, id / 2.123 * 100);
                break;
            case "Organization":
                res = new Organization(id, "Organization " + id);
                break;
            case "Account":
                res = new Account(id);
                break;
            case "Person1":
                res = new Person1(id);
                break;
            case "Person2":
                res = new Person2(id);
                break;
            case "Person8":
                res = new Person8(id);
                break;
            case "String":
                res = String.valueOf(id);
        }

        return res;
    }

    /**
     * @return array of key cache classes
     */
    public static Class[] keyClasses() {
        return keyClasses;
    }

    /**
     * @return array of value chache classes
     */
    public static Class[] valueClasses() {
        return valClasses;
    }
}

@@ -2088,32 +2088,456 @@
 8.class%0A    %7D;%0A%0A
+    /**%0A     * Simple of classes.%0A     * Upper approximate size of value 24 bytes.%0A     */%0A    private static Class%5B%5D simpleClasses = %7B%0A        Account.class,%0A        Person1.class,%0A        Person2.class,%0A    %7D;%0A%0A    /**%0A     * Fat of classes.%0A     * Upper approximate size of value 128 bytes.%0A     */%0A    private static Class%5B%5D fatClasses = %7B%0A        Person.class,%0A        Person8.class,%0A        Organization.class%0A    %7D;%0A%0A
     /**%0A     * @
@@ -3173,26 +3173,10 @@
 s = 
-Double.valueOf(
 id
-)
 ;%0A  
@@ -4961,25 +4961,25 @@
 @return 
-a
+A
 rray of 
 value ch
@@ -4974,19 +4974,162 @@
  of 
+cache 
 value c
-hach
+lasses%0A     */%0A    public static Class%5B%5D valueClasses() %7B%0A        return valClasses;%0A    %7D%0A%0A    /**%0A     * @return Array of cache value simpl
 e cl
@@ -5125,32 +5125,33 @@
 e simple classes
+.
 %0A     */%0A    pub
@@ -5161,33 +5161,39 @@
  static Class%5B%5D 
-v
+simpleV
 alueClasses() %7B%0A
@@ -5199,35 +5199,183 @@
 %0A        return 
-val
+simpleClasses;%0A    %7D%0A%0A    /**%0A     * @return Array of cache value fat classes.%0A     */%0A    public static Class%5B%5D fatValueClasses() %7B%0A        return fat
 Classes;%0A    %7D%0A%7D

load tests based on SB cases