/*
 * 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.
 */

import {nonEmpty} from 'app/utils/lodashMixins';

import { Bean } from './Beans';

import AbstractTransformer from './AbstractTransformer';
import StringBuilder from './StringBuilder';
import VersionService from 'app/services/Version.service';

const versionService = new VersionService();
const STORE_FACTORY = ['org.apache.ignite.cache.store.jdbc.CacheJdbcPojoStoreFactory'];

// Descriptors for generation of demo data.
const PREDEFINED_QUERIES = [
    {
        schema: 'CARS',
        type: 'PARKING',
        create: [
            'CREATE TABLE IF NOT EXISTS CARS.PARKING (',
            'ID       INTEGER     NOT NULL PRIMARY KEY,',
            'NAME     VARCHAR(50) NOT NULL,',
            'CAPACITY INTEGER NOT NULL)'
        ],
        clearQuery: ['DELETE FROM CARS.PARKING'],
        insertCntConsts: [{name: 'DEMO_MAX_PARKING_CNT', val: 5, comment: 'How many parkings to generate.'}],
        insertPattern: ['INSERT INTO CARS.PARKING(ID, NAME, CAPACITY) VALUES(?, ?, ?)'],
        fillInsertParameters(sb) {
            sb.append('stmt.setInt(1, id);');
            sb.append('stmt.setString(2, "Parking #" + (id + 1));');
            sb.append('stmt.setInt(3, 10 + rnd.nextInt(20));');
        },
        selectQuery: ['SELECT * FROM PARKING WHERE CAPACITY >= 20']
    },
    {
        schema: 'CARS',
        type: 'CAR',
        create: [
            'CREATE TABLE IF NOT EXISTS CARS.CAR (',
            'ID         INTEGER NOT NULL PRIMARY KEY,',
            'PARKING_ID INTEGER NOT NULL,',
            'NAME       VARCHAR(50) NOT NULL);'
        ],
        clearQuery: ['DELETE FROM CARS.CAR'],
        rndRequired: true,
        insertCntConsts: [
            {name: 'DEMO_MAX_CAR_CNT', val: 10, comment: 'How many cars to generate.'},
            {name: 'DEMO_MAX_PARKING_CNT', val: 5, comment: 'How many parkings to generate.'}
        ],
        insertPattern: ['INSERT INTO CARS.CAR(ID, PARKING_ID, NAME) VALUES(?, ?, ?)'],
        fillInsertParameters(sb) {
            sb.append('stmt.setInt(1, id);');
            sb.append('stmt.setInt(2, rnd.nextInt(DEMO_MAX_PARKING_CNT));');
            sb.append('stmt.setString(3, "Car #" + (id + 1));');
        },
        selectQuery: ['SELECT * FROM CAR WHERE PARKINGID = 2']
    },
    {
        type: 'COUNTRY',
        create: [
            'CREATE TABLE IF NOT EXISTS COUNTRY (',
            'ID         INTEGER NOT NULL PRIMARY KEY,',
            'NAME       VARCHAR(50),',
            'POPULATION INTEGER NOT NULL);'
        ],
        clearQuery: ['DELETE FROM COUNTRY'],
        insertCntConsts: [{name: 'DEMO_MAX_COUNTRY_CNT', val: 5, comment: 'How many countries to generate.'}],
        insertPattern: ['INSERT INTO COUNTRY(ID, NAME, POPULATION) VALUES(?, ?, ?)'],
        fillInsertParameters(sb) {
            sb.append('stmt.setInt(1, id);');
            sb.append('stmt.setString(2, "Country #" + (id + 1));');
            sb.append('stmt.setInt(3, 10000000 + rnd.nextInt(100000000));');
        },
        selectQuery: ['SELECT * FROM COUNTRY WHERE POPULATION BETWEEN 15000000 AND 25000000']
    },
    {
        type: 'DEPARTMENT',
        create: [
            'CREATE TABLE IF NOT EXISTS DEPARTMENT (',
            'ID         INTEGER NOT NULL PRIMARY KEY,',
            'COUNTRY_ID INTEGER NOT NULL,',
            'NAME       VARCHAR(50) NOT NULL);'
        ],
        clearQuery: ['DELETE FROM DEPARTMENT'],
        rndRequired: true,
        insertCntConsts: [
            {name: 'DEMO_MAX_DEPARTMENT_CNT', val: 5, comment: 'How many departments to generate.'},
            {name: 'DEMO_MAX_COUNTRY_CNT', val: 5, comment: 'How many countries to generate.'}
        ],
        insertPattern: ['INSERT INTO DEPARTMENT(ID, COUNTRY_ID, NAME) VALUES(?, ?, ?)'],
        fillInsertParameters(sb) {
            sb.append('stmt.setInt(1, id);');
            sb.append('stmt.setInt(2, rnd.nextInt(DEMO_MAX_COUNTRY_CNT));');
            sb.append('stmt.setString(3, "Department #" + (id + 1));');
        },
        selectQuery: ['SELECT * FROM DEPARTMENT']
    },
    {
        type: 'EMPLOYEE',
        create: [
            'CREATE TABLE IF NOT EXISTS EMPLOYEE (',
            'ID            INTEGER NOT NULL PRIMARY KEY,',
            'DEPARTMENT_ID INTEGER NOT NULL,',
            'MANAGER_ID    INTEGER,',
            'FIRST_NAME    VARCHAR(50) NOT NULL,',
            'LAST_NAME     VARCHAR(50) NOT NULL,',
            'EMAIL         VARCHAR(50) NOT NULL,',
            'PHONE_NUMBER  VARCHAR(50),',
            'HIRE_DATE     DATE        NOT NULL,',
            'JOB           VARCHAR(50) NOT NULL,',
            'SALARY        DOUBLE);'
        ],
        clearQuery: ['DELETE FROM EMPLOYEE'],
        rndRequired: true,
        insertCntConsts: [
            {name: 'DEMO_MAX_EMPLOYEE_CNT', val: 10, comment: 'How many employees to generate.'},
            {name: 'DEMO_MAX_DEPARTMENT_CNT', val: 5, comment: 'How many departments to generate.'}
        ],
        customGeneration(sb, conVar, stmtVar) {
            sb.append(`${stmtVar} = ${conVar}.prepareStatement("INSERT INTO EMPLOYEE(ID, DEPARTMENT_ID, MANAGER_ID, FIRST_NAME, LAST_NAME, EMAIL, PHONE_NUMBER, HIRE_DATE, JOB, SALARY) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");`);

            sb.emptyLine();

            sb.startBlock('for (int id = 0; id < DEMO_MAX_EMPLOYEE_CNT; id ++) {');

            sb.append('int depId = rnd.nextInt(DEMO_MAX_DEPARTMENT_CNT);');

            sb.emptyLine();

            sb.append('stmt.setInt(1, DEMO_MAX_DEPARTMENT_CNT + id);');
            sb.append('stmt.setInt(2, depId);');
            sb.append('stmt.setInt(3, depId);');
            sb.append('stmt.setString(4, "First name manager #" + (id + 1));');
            sb.append('stmt.setString(5, "Last name manager#" + (id + 1));');
            sb.append('stmt.setString(6, "Email manager#" + (id + 1));');
            sb.append('stmt.setString(7, "Phone number manager#" + (id + 1));');
            sb.append('stmt.setString(8, "2014-01-01");');
            sb.append('stmt.setString(9, "Job manager #" + (id + 1));');
            sb.append('stmt.setDouble(10, 600.0 + rnd.nextInt(300));');

            sb.emptyLine();

            sb.append('stmt.executeUpdate();');

            sb.endBlock('}');
        },
        selectQuery: ['SELECT * FROM EMPLOYEE WHERE SALARY > 700']
    }
];

// Var name generator function.
const beanNameSeed = () => {
    let idx = '';
    const names = [];

    return (bean) => {
        let name;

        while (_.includes(names, name = `${bean.id}${idx ? '_' + idx : idx}`))
            idx++;

        names.push(name);

        return name;
    };
};

export default class IgniteJavaTransformer extends AbstractTransformer {
    // Mapping for objects to method call.
    static METHOD_MAPPING = {
        'org.apache.ignite.configuration.CacheConfiguration': {
            prefix: 'cache',
            name: 'name',
            args: '',
            generator: (sb, id, ccfg) => {
                const cacheName = ccfg.findProperty('name').value;
                const dataSources = IgniteJavaTransformer.collectDataSources(ccfg);

                const javadoc = [
                    `Create configuration for cache "${cacheName}".`,
                    '',
                    '@return Configured cache.'
                ];

                if (dataSources.length)
                    javadoc.push('@throws Exception if failed to create cache configuration.');

                IgniteJavaTransformer.commentBlock(sb, ...javadoc);
                sb.startBlock(`public static CacheConfiguration ${id}()${dataSources.length ? ' throws Exception' : ''} {`);

                IgniteJavaTransformer.constructBean(sb, ccfg, [], true);

                sb.emptyLine();
                sb.append(`return ${ccfg.id};`);

                sb.endBlock('}');

                return sb;
            }
        },
        'org.apache.ignite.cache.store.jdbc.JdbcType': {
            prefix: 'jdbcType',
            name: 'valueType',
            args: 'ccfg.getName()',
            generator: (sb, name, jdbcType) => {
                const javadoc = [
                    `Create JDBC type for "${name}".`,
                    '',
                    '@param cacheName Cache name.',
                    '@return Configured JDBC type.'
                ];

                IgniteJavaTransformer.commentBlock(sb, ...javadoc);
                sb.startBlock(`private static JdbcType ${name}(String cacheName) {`);

                const cacheName = jdbcType.findProperty('cacheName');

                cacheName.clsName = 'var';
                cacheName.value = 'cacheName';

                IgniteJavaTransformer.constructBean(sb, jdbcType);

                sb.emptyLine();
                sb.append(`return ${jdbcType.id};`);

                sb.endBlock('}');

                return sb;
            }
        }
    };

    // Append comment line.
    static comment(sb, ...lines) {
        _.forEach(lines, (line) => sb.append(`// ${line}`));
    }

    // Append comment block.
    static commentBlock(sb, ...lines) {
        if (lines.length === 1)
            sb.append(`/** ${_.head(lines)} **/`);
        else {
            sb.append('/**');

            _.forEach(lines, (line) => sb.append(` * ${line}`));

            sb.append(' **/');
        }
    }

    /**
     * @param {Bean} bean
     */
    static _newBean(bean) {
        const shortClsName = this.javaTypes.shortClassName(bean.clsName);

        if (_.isEmpty(bean.arguments))
            return `new ${shortClsName}()`;

        const args = _.map(bean.arguments, (arg) => {
            switch (arg.clsName) {
                case 'MAP':
                    return arg.id;
                case 'BEAN':
                    return this._newBean(arg.value);
                default:
                    return this._toObject(arg.clsName, arg.value);
            }
        });

        if (bean.factoryMtd)
            return `${shortClsName}.${bean.factoryMtd}(${args.join(', ')})`;

        return `new ${shortClsName}(${args.join(', ')})`;
    }

    /**
     * @param {StringBuilder} sb
     * @param {String} parentId
     * @param {String} propertyName
     * @param {String} value
     * @private
     */
    static _setProperty(sb, parentId, propertyName, value) {
        sb.append(`${parentId}.set${_.upperFirst(propertyName)}(${value});`);
    }

    /**
     * @param {StringBuilder} sb
     * @param {Array.<String>} vars
     * @param {Boolean} limitLines
     * @param {Bean} bean
     * @param {String} id

     * @private
     */
    static constructBean(sb, bean, vars = [], limitLines = false, id = bean.id) {
        _.forEach(bean.arguments, (arg) => {
            switch (arg.clsName) {
                case 'MAP':
                    this._constructMap(sb, arg, vars);

                    sb.emptyLine();

                    break;

                default:
                    if (this._isBean(arg.clsName) && arg.value.isComplex()) {
                        this.constructBean(sb, arg.value, vars, limitLines);

                        sb.emptyLine();
                    }
            }
        });

        const clsName = this.javaTypes.shortClassName(bean.clsName);

        sb.append(`${this.varInit(clsName, id, vars)} = ${this._newBean(bean)};`);

        if (nonEmpty(bean.properties)) {
            sb.emptyLine();

            this._setProperties(sb, bean, vars, limitLines, id);
        }
    }

    /**
     * @param {StringBuilder} sb
     * @param {Bean} bean
     * @param {Array.<String>} vars
     * @param {Boolean} limitLines
     * @private
     */
    static constructStoreFactory(sb, bean, vars, limitLines = false) {
        const shortClsName = this.javaTypes.shortClassName(bean.clsName);

        if (_.includes(vars, bean.id))
            sb.append(`${bean.id} = ${this._newBean(bean)};`);
        else {
            vars.push(bean.id);

            sb.append(`${shortClsName} ${bean.id} = ${this._newBean(bean)};`);
        }

        sb.emptyLine();

        sb.startBlock(`${bean.id}.setDataSourceFactory(new Factory<DataSource>() {`);
        this.commentBlock(sb, '{@inheritDoc}');
        sb.startBlock('@Override public DataSource create() {');

        sb.append(`return DataSources.INSTANCE_${bean.findProperty('dataSourceBean').id};`);

        sb.endBlock('};');
        sb.endBlock('});');

        const storeFactory = _.cloneDeep(bean);

        _.remove(storeFactory.properties, (p) => _.includes(['dataSourceBean'], p.name));

        if (storeFactory.properties.length) {
            sb.emptyLine();

            this._setProperties(sb, storeFactory, vars, limitLines);
        }
    }

    static _isBean(clsName) {
        return this.javaTypes.nonBuiltInClass(clsName) && this.javaTypesNonEnum.nonEnum(clsName) && _.includes(clsName, '.');
    }

    static _toObject(clsName, val) {
        const items = _.isArray(val) ? val : [val];

        if (clsName === 'EVENTS') {
            const lastIdx = items.length - 1;

            return [..._.map(items, (v, idx) => (idx === 0 ? 'new int[] {' : ' ') + v.label + (lastIdx === idx ? '}' : ''))];
        }

        return _.map(items, (item) => {
            if (_.isNil(item))
                return 'null';

            switch (clsName) {
                case 'byte':
                    return `(byte) ${item}`;
                case 'float':
                    return `${item}f`;
                case 'double':
                    return `${item}`;
                case 'long':
                    return `${item}L`;
                case 'java.io.Serializable':
                case 'java.lang.String':
                    return `"${item.replace(/\\/g, '\\\\').replace(/"/g, '\\"')}"`;
                case 'PATH':
                case 'PATH_ARRAY':
                    return `"${item.replace(/\\/g, '\\\\')}"`;
                case 'java.lang.Class':
                    return `${this.javaTypes.shortClassName(item)}.class`;
                case 'java.util.UUID':
                    return `UUID.fromString("${item}")`;
                case 'PROPERTY':
                    return `props.getProperty("${item}")`;
                case 'PROPERTY_CHAR':
                    return `props.getProperty("${item}").toCharArray()`;
                case 'PROPERTY_INT':
                    return `Integer.parseInt(props.getProperty("${item}"))`;
                default:
                    if (this._isBean(clsName) || val instanceof Bean) {
                        if (item.isComplex())
                            return item.id;

                        return this._newBean(item);
                    }

                    if (this.javaTypesNonEnum.nonEnum(clsName))
                        return item;

                    return `${this.javaTypes.shortClassName(clsName)}.${item}`;
            }
        });
    }

    static _mapperId(mapper) {
        return (item) => this.javaTypes.toJavaName(mapper.prefix, item.findProperty(mapper.name).value);
    }

    static _constructBeans(sb, type, items, vars, limitLines) {
        if (this._isBean(type)) {
            // Construct objects inline for preview or simple objects.
            const mapper = this.METHOD_MAPPING[type];

            const nextId = mapper ? this._mapperId(mapper) : beanNameSeed();

            // Prepare objects refs.
            return _.map(items, (item) => {
                if (limitLines && mapper)
                    return nextId(item) + (limitLines ? `(${mapper.args})` : '');

                if (item.isComplex()) {
                    const id = nextId(item);

                    this.constructBean(sb, item, vars, limitLines, id);

                    sb.emptyLine();

                    return id;
                }

                return this._newBean(item);
            });
        }

        return this._toObject(type, items);
    }

    /**
     *
     * @param sb
     * @param parentId
     * @param arrProp
     * @param vars
     * @param limitLines
     * @private
     */
    static _setVarArg(sb, parentId, arrProp, vars, limitLines) {
        const refs = this._constructBeans(sb, arrProp.typeClsName, arrProp.items, vars, limitLines);

        // Set refs to property.
        if (refs.length === 1)
            this._setProperty(sb, parentId, arrProp.name, _.head(refs));
        else {
            sb.startBlock(`${parentId}.set${_.upperFirst(arrProp.name)}(`);

            const lastIdx = refs.length - 1;

            _.forEach(refs, (ref, idx) => {
                sb.append(ref + (lastIdx !== idx ? ',' : ''));
            });

            sb.endBlock(');');
        }
    }

    /**
     *
     * @param sb
     * @param parentId
     * @param arrProp
     * @param vars
     * @param limitLines
     * @private
     */
    static _setArray(sb, parentId, arrProp, vars, limitLines) {
        const refs = this._constructBeans(sb, arrProp.typeClsName, arrProp.items, vars, limitLines);

        const arrType = this.javaTypes.shortClassName(arrProp.typeClsName);

        // Set refs to property.
        sb.startBlock(`${parentId}.set${_.upperFirst(arrProp.name)}(new ${arrType}[] {`);

        const lastIdx = refs.length - 1;

        _.forEach(refs, (ref, idx) => sb.append(ref + (lastIdx !== idx ? ',' : '')));

        sb.endBlock('});');
    }

    static _constructMap(sb, map, vars = []) {
        const keyClsName = this.javaTypes.shortClassName(map.keyClsName);
        const valClsName = this.javaTypes.shortClassName(map.valClsName);

        const genericTypeShort = map.keyClsGenericType ? this.javaTypes.shortClassName(map.keyClsGenericType) : '';
        const keyClsGeneric = map.keyClsGenericType ?
            map.isKeyClsGenericTypeExtended ? `<? extends ${genericTypeShort}>` : `<${genericTypeShort}>`
            : '';

        const mapClsName = map.ordered ? 'LinkedHashMap' : 'HashMap';

        const type = `${mapClsName}<${keyClsName}${keyClsGeneric}, ${valClsName}>`;

        sb.append(`${this.varInit(type, map.id, vars)} = new ${mapClsName}<>();`);

        sb.emptyLine();

        _.forEach(map.entries, (entry) => {
            const key = this._toObject(map.keyClsName, entry[map.keyField]);
            const val = entry[map.valField];

            if (_.isArray(val) && map.valClsName === 'java.lang.String') {
                if (val.length > 1) {
                    sb.startBlock(`${map.id}.put(${key},`);

                    _.forEach(val, (line, idx) => {
                        sb.append(`"${line}"${idx !== val.length - 1 ? ' +' : ''}`);
                    });

                    sb.endBlock(');');
                }
                else
                    sb.append(`${map.id}.put(${key}, ${this._toObject(map.valClsName, _.head(val))});`);
            }
            else
                sb.append(`${map.id}.put(${key}, ${this._toObject(map.valClsNameShow || map.valClsName, val)});`);
        });
    }

    static varInit(type, id, vars) {
        if (_.includes(vars, id))
            return id;

        vars.push(id);

        return `${type} ${id}`;
    }

    /**
     *
     * @param {StringBuilder} sb
     * @param {Bean} bean
     * @param {String} id
     * @param {Array.<String>} vars
     * @param {Boolean} limitLines
     * @returns {StringBuilder}
     */
    static _setProperties(sb = new StringBuilder(), bean, vars = [], limitLines = false, id = bean.id) {
        _.forEach(bean.properties, (prop, idx) => {
            switch (prop.clsName) {
                case 'DATA_SOURCE':
                    this._setProperty(sb, id, 'dataSource', `DataSources.INSTANCE_${prop.id}`);

                    break;
                case 'EVENT_TYPES':
                    if (prop.eventTypes.length === 1) {
                        const evtGrp = _.head(prop.eventTypes);

                        this._setProperty(sb, id, prop.name, evtGrp.label);
                    }
                    else {
                        const evtGrp = _.map(prop.eventTypes, 'label');

                        sb.append(`int[] ${prop.id} = new int[${_.head(evtGrp)}.length`);

                        _.forEach(_.tail(evtGrp), (evtGrp) => {
                            sb.append(`    + ${evtGrp}.length`);
                        });

                        sb.append('];');

                        sb.emptyLine();

                        sb.append('int k = 0;');

                        _.forEach(evtGrp, (evtGrp, evtIdx) => {
                            sb.emptyLine();

                            sb.append(`System.arraycopy(${evtGrp}, 0, ${prop.id}, k, ${evtGrp}.length);`);

                            if (evtIdx < evtGrp.length - 1)
                                sb.append(`k += ${evtGrp}.length;`);
                        });

                        sb.emptyLine();

                        sb.append(`cfg.setIncludeEventTypes(${prop.id});`);
                    }

                    break;
                case 'ARRAY':
                    if (prop.varArg)
                        this._setVarArg(sb, id, prop, vars, limitLines);
                    else
                        this._setArray(sb, id, prop, vars, limitLines);

                    break;
                case 'PATH_ARRAY':
                    if (prop.varArg)
                        this._setVarArg(sb, id, prop, this._toObject(prop.clsName, prop.items), limitLines);
                    else
                        this._setArray(sb, id, prop, this._toObject(prop.clsName, prop.items), limitLines);

                    break;
                case 'COLLECTION':
                    const nonBean = !this._isBean(prop.typeClsName);

                    if (nonBean && prop.implClsName === 'java.util.ArrayList') {
                        const items = _.map(prop.items, (item) => this._toObject(prop.typeClsName, item));

                        if (items.length > 1) {
                            sb.startBlock(`${id}.set${_.upperFirst(prop.name)}(Arrays.asList(`);

                            _.forEach(items, (item, i) => sb.append(item + (i !== items.length - 1 ? ',' : '')));

                            sb.endBlock('));');
                        }
                        else
                            this._setProperty(sb, id, prop.name, `Arrays.asList(${items})`);
                    }
                    else {
                        const colTypeClsName = this.javaTypes.shortClassName(prop.typeClsName);
                        const implClsName = this.javaTypes.shortClassName(prop.implClsName);

                        sb.append(`${this.varInit(`${implClsName}<${colTypeClsName}>`, prop.id, vars)} = new ${implClsName}<>();`);

                        sb.emptyLine();

                        if (nonBean) {
                            _.forEach(this._toObject(colTypeClsName, prop.items), (item) => {
                                if (this.javaTypesNonEnum.nonEnum(prop.typeClsName))
                                    sb.append(`${prop.id}.add("${item}");`);
                                else
                                    sb.append(`${prop.id}.add(${item});`);

                                sb.emptyLine();
                            });
                        }
                        else {
                            _.forEach(prop.items, (item) => {
                                this.constructBean(sb, item, vars, limitLines);

                                sb.append(`${prop.id}.add(${item.id});`);

                                sb.emptyLine();
                            });
                        }

                        this._setProperty(sb, id, prop.name, prop.id);
                    }

                    break;
                case 'MAP':
                    this._constructMap(sb, prop, vars);

                    if (nonEmpty(prop.entries))
                        sb.emptyLine();

                    this._setProperty(sb, id, prop.name, prop.id);

                    break;
                case 'java.util.Properties':
                    sb.append(`${this.varInit('Properties', prop.id, vars)} = new Properties();`);

                    if (nonEmpty(prop.entries))
                        sb.emptyLine();

                    _.forEach(prop.entries, (entry) => {
                        const key = this._toObject('java.lang.String', entry.name);
                        const val = this._toObject('java.lang.String', entry.value);

                        sb.append(`${prop.id}.setProperty(${key}, ${val});`);
                    });

                    sb.emptyLine();

                    this._setProperty(sb, id, prop.name, prop.id);

                    break;
                case 'BEAN':
                    const embedded = prop.value;

                    if (_.includes(STORE_FACTORY, embedded.clsName)) {
                        this.constructStoreFactory(sb, embedded, vars, limitLines);

                        sb.emptyLine();

                        this._setProperty(sb, id, prop.name, embedded.id);
                    }
                    else if (embedded.isComplex()) {
                        this.constructBean(sb, embedded, vars, limitLines);

                        sb.emptyLine();

                        this._setProperty(sb, id, prop.name, embedded.id);
                    }
                    else
                        this._setProperty(sb, id, prop.name, this._newBean(embedded));

                    break;
                default:
                    this._setProperty(sb, id, prop.name, this._toObject(prop.clsName, prop.value));
            }

            this._emptyLineIfNeeded(sb, bean.properties, idx);
        });

        return sb;
    }

    static _collectMapImports(prop) {
        const imports = [];

        imports.push(prop.ordered ? 'java.util.LinkedHashMap' : 'java.util.HashMap');
        imports.push(prop.keyClsName);
        imports.push(prop.valClsName);

        if (prop.keyClsGenericType)
            imports.push(prop.keyClsGenericType);

        return imports;
    }

    static collectBeanImports(bean) {
        const imports = [bean.clsName];

        _.forEach(bean.arguments, (arg) => {
            switch (arg.clsName) {
                case 'BEAN':
                    imports.push(...this.collectPropertiesImports(arg.value.properties));

                    break;
                case 'java.lang.Class':
                    imports.push(this.javaTypes.fullClassName(arg.value));

                    break;

                case 'MAP':
                    imports.push(...this._collectMapImports(arg));

                    break;
                default:
                    imports.push(arg.clsName);
            }
        });

        imports.push(...this.collectPropertiesImports(bean.properties));

        if (_.includes(STORE_FACTORY, bean.clsName))
            imports.push('javax.sql.DataSource', 'javax.cache.configuration.Factory');

        return imports;
    }

    /**
     * @param {Array.<Object>} props
     * @returns {Array.<String>}
     */
    static collectPropertiesImports(props) {
        const imports = [];

        _.forEach(props, (prop) => {
            switch (prop.clsName) {
                case 'DATA_SOURCE':
                    imports.push(prop.value.clsName);

                    break;
                case 'PROPERTY':
                case 'PROPERTY_CHAR':
                case 'PROPERTY_INT':
                    imports.push('java.io.InputStream', 'java.util.Properties');

                    break;
                case 'BEAN':
                    imports.push(...this.collectBeanImports(prop.value));

                    break;
                case 'ARRAY':
                    if (!prop.varArg)
                        imports.push(prop.typeClsName);

                    if (this._isBean(prop.typeClsName))
                        _.forEach(prop.items, (item) => imports.push(...this.collectBeanImports(item)));

                    if (prop.typeClsName === 'java.lang.Class')
                        _.forEach(prop.items, (item) => imports.push(item));

                    break;
                case 'COLLECTION':
                    imports.push(prop.typeClsName);

                    if (this._isBean(prop.typeClsName)) {
                        _.forEach(prop.items, (item) => imports.push(...this.collectBeanImports(item)));

                        imports.push(prop.implClsName);
                    }
                    else if (prop.implClsName === 'java.util.ArrayList')
                        imports.push('java.util.Arrays');
                    else
                        imports.push(prop.implClsName);

                    break;
                case 'MAP':
                    imports.push(...this._collectMapImports(prop));

                    break;
                default:
                    if (!this.javaTypesNonEnum.nonEnum(prop.clsName))
                        imports.push(prop.clsName);
            }
        });

        return imports;
    }

    static _prepareImports(imports) {
        return _.sortedUniq(_.sortBy(_.filter(imports, (cls) => !_.startsWith(cls, 'java.lang.') && _.includes(cls, '.'))));
    }

    /**
     * @param {Bean} bean
     * @returns {Array.<String>}
     */
    static collectStaticImports(bean) {
        const imports = [];

        _.forEach(bean.properties, (prop) => {
            switch (prop.clsName) {
                case 'EVENT_TYPES':
                    _.forEach(prop.eventTypes, (grp) => {
                        imports.push(`${grp.class}.${grp.value}`);
                    });

                    break;

                case 'MAP':
                    if (prop.valClsNameShow === 'EVENTS') {
                        _.forEach(prop.entries, (lnr) => {
                            _.forEach(lnr.eventTypes, (type) => imports.push(`${type.class}.${type.label}`));
                        });
                    }

                    break;

                default:
                    // No-op.
            }
        });

        return imports;
    }

    /**
     * @param {Bean} bean
     * @returns {Object}
     */
    static collectBeansWithMapping(bean) {
        const beans = {};

        _.forEach(bean.properties, (prop) => {
            switch (prop.clsName) {
                case 'BEAN':
                    _.merge(beans, this.collectBeansWithMapping(prop.value));

                    break;
                case 'ARRAY':
                    if (this._isBean(prop.typeClsName)) {
                        const mapper = this.METHOD_MAPPING[prop.typeClsName];

                        const mapperId = mapper ? this._mapperId(mapper) : null;

                        _.reduce(prop.items, (acc, item) => {
                            if (mapperId)
                                acc[mapperId(item)] = item;

                            _.merge(acc, this.collectBeansWithMapping(item));

                            return acc;
                        }, beans);
                    }

                    break;
                default:
                    // No-op.
            }
        });

        return beans;
    }

    /**
     * Build Java startup class with configuration.
     *
     * @param {Bean} cfg
     * @param {Object} targetVer Version of Ignite for generated project.
     * @param pkg Package name.
     * @param {String} clsName Class name for generate factory class otherwise generate code snippet.
     * @param {Array.<Object>} clientNearCaches Is client node.
     * @returns {StringBuilder}
     */
    static igniteConfiguration(cfg, targetVer, pkg, clsName, clientNearCaches) {
        const available = versionService.since.bind(versionService, targetVer.ignite);

        const sb = new StringBuilder();

        sb.append(`package ${pkg};`);
        sb.emptyLine();

        const imports = this.collectBeanImports(cfg);

        const nearCacheBeans = [];

        if (nonEmpty(clientNearCaches)) {
            imports.push('org.apache.ignite.configuration.NearCacheConfiguration');

            _.forEach(clientNearCaches, (cache) => {
                const nearCacheBean = this.generator.cacheNearClient(cache, available);

                nearCacheBean.cacheName = cache.name;

                imports.push(...this.collectBeanImports(nearCacheBean));

                nearCacheBeans.push(nearCacheBean);
            });
        }

        if (_.includes(imports, 'oracle.jdbc.pool.OracleDataSource'))
            imports.push('java.sql.SQLException');

        const hasProps = this.hasProperties(cfg);

        if (hasProps)
            imports.push('java.util.Properties', 'java.io.InputStream');

        _.forEach(this._prepareImports(imports), (cls) => sb.append(`import ${cls};`));

        sb.emptyLine();

        const staticImports = this._prepareImports(this.collectStaticImports(cfg));

        if (staticImports.length) {
            _.forEach(this._prepareImports(staticImports), (cls) => sb.append(`import static ${cls};`));

            sb.emptyLine();
        }

        this.mainComment(sb);
        sb.startBlock(`public class ${clsName} {`);

        // 2. Add external property file
        if (hasProps) {
            this.commentBlock(sb, 'Secret properties loading.');
            sb.append('private static final Properties props = new Properties();');
            sb.emptyLine();
            sb.startBlock('static {');
            sb.startBlock('try (InputStream in = IgniteConfiguration.class.getClassLoader().getResourceAsStream("secret.properties")) {');
            sb.append('props.load(in);');
            sb.endBlock('}');
            sb.startBlock('catch (Exception ignored) {');
            sb.append('// No-op.');
            sb.endBlock('}');
            sb.endBlock('}');
            sb.emptyLine();
        }

        // 3. Add data sources.
        const dataSources = this.collectDataSources(cfg);

        if (dataSources.length) {
            this.commentBlock(sb, 'Helper class for datasource creation.');
            sb.startBlock('public static class DataSources {');

            _.forEach(dataSources, (ds, idx) => {
                const dsClsName = this.javaTypes.shortClassName(ds.clsName);

                if (idx !== 0)
                    sb.emptyLine();

                sb.append(`public static final ${dsClsName} INSTANCE_${ds.id} = create${ds.id}();`);
                sb.emptyLine();

                sb.startBlock(`private static ${dsClsName} create${ds.id}() {`);

                if (dsClsName === 'OracleDataSource')
                    sb.startBlock('try {');

                this.constructBean(sb, ds);

                sb.emptyLine();
                sb.append(`return ${ds.id};`);

                if (dsClsName === 'OracleDataSource') {
                    sb.endBlock('}');
                    sb.startBlock('catch (SQLException ex) {');
                    sb.append('throw new Error(ex);');
                    sb.endBlock('}');
                }

                sb.endBlock('}');
            });

            sb.endBlock('}');

            sb.emptyLine();
        }

        _.forEach(nearCacheBeans, (nearCacheBean) => {
            this.commentBlock(sb, `Configuration of near cache for cache: ${nearCacheBean.cacheName}.`,
                '',
                '@return Near cache configuration.',
                '@throws Exception If failed to construct near cache configuration instance.'
            );

            sb.startBlock(`public static NearCacheConfiguration ${nearCacheBean.id}() throws Exception {`);

            this.constructBean(sb, nearCacheBean);
            sb.emptyLine();

            sb.append(`return ${nearCacheBean.id};`);
            sb.endBlock('}');

            sb.emptyLine();
        });

        this.commentBlock(sb, 'Configure grid.',
            '',
            '@return Ignite configuration.',
            '@throws Exception If failed to construct Ignite configuration instance.'
        );
        sb.startBlock('public static IgniteConfiguration createConfiguration() throws Exception {');

        this.constructBean(sb, cfg, [], true);

        sb.emptyLine();

        sb.append(`return ${cfg.id};`);

        sb.endBlock('}');

        const beans = this.collectBeansWithMapping(cfg);

        _.forEach(beans, (bean, id) => {
            sb.emptyLine();

            this.METHOD_MAPPING[bean.clsName].generator(sb, id, bean);
        });

        sb.endBlock('}');

        return sb;
    }

    static cluster(cluster, targetVer, pkg, clsName, client) {
        const cfg = this.generator.igniteConfiguration(cluster, targetVer, client);

        const clientNearCaches = client ? _.filter(cluster.caches, (cache) =>
            cache.cacheMode === 'PARTITIONED' && _.get(cache, 'clientNearConfiguration.enabled')) : [];

        return this.igniteConfiguration(cfg, targetVer, pkg, clsName, clientNearCaches);
    }

    /**
     * Generate source code for type by its domain model.
     *
     * @param fullClsName Full class name.
     * @param fields Fields.
     * @param addConstructor If 'true' then empty and full constructors should be generated.
     * @returns {StringBuilder}
     */
    static pojo(fullClsName, fields, addConstructor) {
        const dotIdx = fullClsName.lastIndexOf('.');

        const pkg = fullClsName.substring(0, dotIdx);
        const clsName = fullClsName.substring(dotIdx + 1);

        const sb = new StringBuilder();

        sb.append(`package ${pkg};`);
        sb.emptyLine();

        const imports = ['java.io.Serializable'];

        _.forEach(fields, (field) => imports.push(this.javaTypes.fullClassName(field.javaFieldType)));

        _.forEach(this._prepareImports(imports), (cls) => sb.append(`import ${cls};`));

        sb.emptyLine();

        this.mainComment(sb,
            `${clsName} definition.`,
            ''
        );
        sb.startBlock(`public class ${clsName} implements Serializable {`);
        sb.append('/** */');
        sb.append('private static final long serialVersionUID = 0L;');
        sb.emptyLine();

        // Generate fields declaration.
        _.forEach(fields, (field) => {
            const fldName = field.javaFieldName;
            const fldType = this.javaTypes.shortClassName(field.javaFieldType);

            sb.append(`/** Value for ${fldName}. */`);
            sb.append(`private ${fldType} ${fldName};`);

            sb.emptyLine();
        });

        // Generate constructors.
        if (addConstructor) {
            this.commentBlock(sb, 'Empty constructor.');
            sb.startBlock(`public ${clsName}() {`);
            this.comment(sb, 'No-op.');
            sb.endBlock('}');

            sb.emptyLine();

            this.commentBlock(sb, 'Full constructor.');

            const arg = (field) => {
                const fldType = this.javaTypes.shortClassName(field.javaFieldType);

                return `${fldType} ${field.javaFieldName}`;
            };

            sb.startBlock(`public ${clsName}(${arg(_.head(fields))}${fields.length === 1 ? ') {' : ','}`);

            _.forEach(_.tail(fields), (field, idx) => {
                sb.append(`${arg(field)}${idx !== fields.length - 2 ? ',' : ') {'}`);
            });

            _.forEach(fields, (field) => sb.append(`this.${field.javaFieldName} = ${field.javaFieldName};`));

            sb.endBlock('}');

            sb.emptyLine();
        }

        // Generate getters and setters methods.
        _.forEach(fields, (field) => {
            const fldType = this.javaTypes.shortClassName(field.javaFieldType);
            const fldName = field.javaFieldName;

            this.commentBlock(sb,
                `Gets ${fldName}`,
                '',
                `@return Value for ${fldName}.`
            );
            sb.startBlock(`public ${fldType} ${this.javaTypes.toJavaName('get', fldName)}() {`);
            sb.append('return ' + fldName + ';');
            sb.endBlock('}');

            sb.emptyLine();

            this.commentBlock(sb,
                `Sets ${fldName}`,
                '',
                `@param ${fldName} New value for ${fldName}.`
            );
            sb.startBlock(`public void ${this.javaTypes.toJavaName('set', fldName)}(${fldType} ${fldName}) {`);
            sb.append(`this.${fldName} = ${fldName};`);
            sb.endBlock('}');

            sb.emptyLine();
        });

        // Generate equals() method.
        this.commentBlock(sb, '{@inheritDoc}');
        sb.startBlock('@Override public boolean equals(Object o) {');
        sb.startBlock('if (this == o)');
        sb.append('return true;');

        sb.endBlock('');

        sb.startBlock(`if (!(o instanceof ${clsName}))`);
        sb.append('return false;');

        sb.endBlock('');

        sb.append(`${clsName} that = (${clsName})o;`);

        _.forEach(fields, (field) => {
            sb.emptyLine();

            const javaName = field.javaFieldName;
            const javaType = field.javaFieldType;

            switch (javaType) {
                case 'float':
                    sb.startBlock(`if (Float.compare(${javaName}, that.${javaName}) != 0)`);

                    break;
                case 'double':
                    sb.startBlock(`if (Double.compare(${javaName}, that.${javaName}) != 0)`);

                    break;
                default:
                    if (this.javaTypes.isPrimitive(javaType))
                        sb.startBlock('if (' + javaName + ' != that.' + javaName + ')');
                    else
                        sb.startBlock('if (' + javaName + ' != null ? !' + javaName + '.equals(that.' + javaName + ') : that.' + javaName + ' != null)');
            }

            sb.append('return false;');

            sb.endBlock('');
        });

        sb.append('return true;');
        sb.endBlock('}');

        sb.emptyLine();

        // Generate hashCode() method.
        this.commentBlock(sb, '{@inheritDoc}');
        sb.startBlock('@Override public int hashCode() {');

        let first = true;
        let tempVar = false;

        _.forEach(fields, (field) => {
            const javaName = field.javaFieldName;
            const javaType = field.javaFieldType;

            let fldHashCode;

            switch (javaType) {
                case 'boolean':
                    fldHashCode = `${javaName} ? 1 : 0`;

                    break;
                case 'byte':
                case 'short':
                    fldHashCode = `(int)${javaName}`;

                    break;
                case 'int':
                    fldHashCode = `${javaName}`;

                    break;
                case 'long':
                    fldHashCode = `(int)(${javaName} ^ (${javaName} >>> 32))`;

                    break;
                case 'float':
                    fldHashCode = `${javaName} != +0.0f ? Float.floatToIntBits(${javaName}) : 0`;

                    break;
                case 'double':
                    sb.append(`${tempVar ? 'ig_hash_temp' : 'long ig_hash_temp'} = Double.doubleToLongBits(${javaName});`);

                    tempVar = true;

                    fldHashCode = '(int) (ig_hash_temp ^ (ig_hash_temp >>> 32))';

                    break;
                default:
                    fldHashCode = `${javaName} != null ? ${javaName}.hashCode() : 0`;
            }

            sb.append(first ? `int res = ${fldHashCode};` : `res = 31 * res + ${fldHashCode.startsWith('(') ? fldHashCode : `(${fldHashCode})`};`);

            first = false;

            sb.emptyLine();
        });

        sb.append('return res;');
        sb.endBlock('}');

        sb.emptyLine();

        this.commentBlock(sb, '{@inheritDoc}');
        sb.startBlock('@Override public String toString() {');
        sb.startBlock(`return "${clsName} [" + `);

        _.forEach(fields, (field, idx) => {
            sb.append(`"${field.javaFieldName}=" + ${field.javaFieldName}${idx < fields.length - 1 ? ' + ", " + ' : ' +'}`);
        });

        sb.endBlock('"]";');
        sb.endBlock('}');

        sb.endBlock('}');

        return sb.asString();
    }

    /**
     * Generate source code for type by its domain models.
     *
     * @param caches List of caches to generate POJOs for.
     * @param addConstructor If 'true' then generate constructors.
     * @param includeKeyFields If 'true' then include key fields into value POJO.
     */
    static pojos(caches, addConstructor, includeKeyFields) {
        const pojos = [];

        _.forEach(caches, (cache) => {
            _.forEach(cache.domains, (domain) => {
                // Process only  domains with 'generatePojo' flag and skip already generated classes.
                if (domain.generatePojo && !_.find(pojos, {valueType: domain.valueType}) &&
                    // Skip domain models without value fields.
                    nonEmpty(domain.valueFields)) {
                    const pojo = {
                        keyType: domain.keyType,
                        valueType: domain.valueType
                    };

                    // Key class generation only if key is not build in java class.
                    if (this.javaTypes.nonBuiltInClass(domain.keyType) && nonEmpty(domain.keyFields))
                        pojo.keyClass = this.pojo(domain.keyType, domain.keyFields, addConstructor);

                    const valueFields = _.clone(domain.valueFields);

                    if (includeKeyFields) {
                        _.forEach(domain.keyFields, (fld) => {
                            if (!_.find(valueFields, {javaFieldName: fld.javaFieldName}))
                                valueFields.push(fld);
                        });
                    }

                    pojo.valueClass = this.pojo(domain.valueType, valueFields, addConstructor);

                    pojos.push(pojo);
                }
            });
        });

        return pojos;
    }

    // Generate creation and execution of cache query.
    static _multilineQuery(sb, query, prefix, postfix) {
        if (_.isEmpty(query))
            return;

        _.forEach(query, (line, ix) => {
            if (ix === 0) {
                if (query.length === 1)
                    sb.append(`${prefix}"${line}"${postfix}`);
                else
                    sb.startBlock(`${prefix}"${line}" +`);
            }
            else
                sb.append(`"${line}"${ix === query.length - 1 ? postfix : ' +'}`);
        });

        if (query.length > 1)
            sb.endBlock('');
        else
            sb.emptyLine();
    }

    // Generate creation and execution of prepared statement.
    static _prepareStatement(sb, conVar, query) {
        this._multilineQuery(sb, query, `${conVar}.prepareStatement(`, ').executeUpdate();');
    }

    static demoStartup(sb, cluster, shortFactoryCls) {
        const cachesWithDataSource = _.filter(cluster.caches, (cache) => {
            const kind = _.get(cache, 'cacheStoreFactory.kind');

            if (kind) {
                const store = cache.cacheStoreFactory[kind];

                return (store.connectVia === 'DataSource' || _.isNil(store.connectVia)) && store.dialect;
            }

            return false;
        });

        const uniqDomains = [];

        // Prepare array of cache and his demo domain model list. Every domain is contained only in first cache.
        const demoTypes = _.reduce(cachesWithDataSource, (acc, cache) => {
            const domains = _.filter(cache.domains, (domain) => nonEmpty(domain.valueFields) &&
                !_.includes(uniqDomains, domain));

            if (nonEmpty(domains)) {
                uniqDomains.push(...domains);

                acc.push({
                    cache,
                    domains
                });
            }

            return acc;
        }, []);

        if (nonEmpty(demoTypes)) {
            // Group domain modes by data source
            const typeByDs = _.groupBy(demoTypes, ({cache}) => cache.cacheStoreFactory[cache.cacheStoreFactory.kind].dataSourceBean);

            let rndNonDefined = true;

            const generatedConsts = [];

            _.forEach(typeByDs, (types) => {
                _.forEach(types, (type) => {
                    _.forEach(type.domains, (domain) => {
                        const valType = domain.valueType.toUpperCase();

                        const desc = _.find(PREDEFINED_QUERIES, (qry) => valType.endsWith(qry.type));

                        if (desc) {
                            if (rndNonDefined && desc.rndRequired) {
                                this.commentBlock(sb, 'Random generator for demo data.');
                                sb.append('private static final Random rnd = new Random();');

                                sb.emptyLine();

                                rndNonDefined = false;
                            }

                            _.forEach(desc.insertCntConsts, (cnt) => {
                                if (!_.includes(generatedConsts, cnt.name)) {
                                    this.commentBlock(sb, cnt.comment);
                                    sb.append(`private static final int ${cnt.name} = ${cnt.val};`);

                                    sb.emptyLine();

                                    generatedConsts.push(cnt.name);
                                }
                            });
                        }
                    });
                });
            });

            // Generation of fill database method
            this.commentBlock(sb, 'Fill data for Demo.');
            sb.startBlock('private static void prepareDemoData() throws SQLException {');

            let firstDs = true;

            _.forEach(typeByDs, (types, ds) => {
                const conVar = ds + 'Con';

                if (firstDs)
                    firstDs = false;
                else
                    sb.emptyLine();

                sb.startBlock(`try (Connection ${conVar} = ${shortFactoryCls}.DataSources.INSTANCE_${ds}.getConnection()) {`);

                let first = true;
                let stmtFirst = true;

                _.forEach(types, (type) => {
                    _.forEach(type.domains, (domain) => {
                        const valType = domain.valueType.toUpperCase();

                        const desc = _.find(PREDEFINED_QUERIES, (qry) => valType.endsWith(qry.type));

                        if (desc) {
                            if (first)
                                first = false;
                            else
                                sb.emptyLine();

                            this.comment(sb, `Generate ${desc.type}.`);

                            if (desc.schema)
                                this._prepareStatement(sb, conVar, [`CREATE SCHEMA IF NOT EXISTS ${desc.schema}`]);

                            this._prepareStatement(sb, conVar, desc.create);

                            this._prepareStatement(sb, conVar, desc.clearQuery);

                            let stmtVar = 'stmt';

                            if (stmtFirst) {
                                stmtFirst = false;

                                stmtVar = 'PreparedStatement stmt';
                            }

                            if (_.isFunction(desc.customGeneration))
                                desc.customGeneration(sb, conVar, stmtVar);
                            else {
                                sb.append(`${stmtVar} = ${conVar}.prepareStatement("${desc.insertPattern}");`);

                                sb.emptyLine();

                                sb.startBlock(`for (int id = 0; id < ${desc.insertCntConsts[0].name}; id ++) {`);

                                desc.fillInsertParameters(sb);

                                sb.emptyLine();

                                sb.append('stmt.executeUpdate();');

                                sb.endBlock('}');
                            }

                            sb.emptyLine();

                            sb.append(`${conVar}.commit();`);
                        }
                    });
                });

                sb.endBlock('}');
            });

            sb.endBlock('}');

            sb.emptyLine();

            this.commentBlock(sb, 'Print result table to console.');
            sb.startBlock('private static void printResult(List<Cache.Entry<Object, Object>> rows) {');
            sb.append('for (Cache.Entry<Object, Object> row: rows)');
            sb.append('    System.out.println(row);');
            sb.endBlock('}');

            sb.emptyLine();

            // Generation of execute queries method.
            this.commentBlock(sb, 'Run demo.');
            sb.startBlock('private static void runDemo(Ignite ignite) throws SQLException {');

            const getType = (fullType) => fullType.substr(fullType.lastIndexOf('.') + 1);

            const cacheLoaded = [];
            let rowVariableDeclared = false;
            firstDs = true;

            _.forEach(typeByDs, (types, ds) => {
                const conVar = ds + 'Con';

                if (firstDs)
                    firstDs = false;
                else
                    sb.emptyLine();

                sb.startBlock(`try (Connection ${conVar} = ${shortFactoryCls}.DataSources.INSTANCE_${ds}.getConnection()) {`);

                let first = true;

                _.forEach(types, (type) => {
                    _.forEach(type.domains, (domain) => {
                        const valType = domain.valueType.toUpperCase();

                        const desc = _.find(PREDEFINED_QUERIES, (qry) => valType.endsWith(qry.type));

                        if (desc) {
                            if (_.isEmpty(desc.selectQuery))
                                return;

                            if (first)
                                first = false;
                            else
                                sb.emptyLine();

                            const cacheName = type.cache.name;

                            if (!_.includes(cacheLoaded, cacheName)) {
                                sb.append(`ignite.cache("${cacheName}").loadCache(null);`);

                                sb.emptyLine();

                                cacheLoaded.push(cacheName);
                            }

                            const varRows = rowVariableDeclared ? 'rows' : 'List<Cache.Entry<Object, Object>> rows';

                            this._multilineQuery(sb, desc.selectQuery, `${varRows} = ignite.cache("${cacheName}").query(new SqlQuery<>("${getType(domain.valueType)}", `, ')).getAll();');

                            sb.append('printResult(rows);');

                            rowVariableDeclared = true;
                        }
                    });
                });

                sb.endBlock('}');
            });

            sb.endBlock('}');
        }
    }

    /**
     * Function to generate java class for node startup with cluster configuration.
     *
     * @param {Object} cluster Cluster to process.
     * @param {String} fullClsName Full class name.
     * @param {String} cfgRef Config.
     * @param {String} [factoryCls] fully qualified class name of configuration factory.
     * @param {Array.<Object>} [clientNearCaches] Is client node.
     */
    static nodeStartup(cluster, fullClsName, cfgRef, factoryCls, clientNearCaches) {
        const dotIdx = fullClsName.lastIndexOf('.');

        const pkg = fullClsName.substring(0, dotIdx);
        const clsName = fullClsName.substring(dotIdx + 1);

        const demo = clsName === 'DemoStartup';

        const sb = new StringBuilder();

        const imports = ['org.apache.ignite.Ignition'];

        if (demo) {
            imports.push('org.h2.tools.Server', 'java.sql.Connection', 'java.sql.PreparedStatement',
                'java.sql.SQLException', 'java.util.Random', 'java.util.List', 'javax.cache.Cache',
                'org.apache.ignite.cache.query.SqlQuery');
        }

        let shortFactoryCls;

        if (factoryCls) {
            imports.push(factoryCls);

            shortFactoryCls = this.javaTypes.shortClassName(factoryCls);
        }

        if ((nonEmpty(clientNearCaches) || demo) && shortFactoryCls)
            imports.push('org.apache.ignite.Ignite');

        sb.append(`package ${pkg};`)
            .emptyLine();

        _.forEach(this._prepareImports(imports), (cls) => sb.append(`import ${cls};`));
        sb.emptyLine();

        if (demo) {
            this.mainComment(sb,
                'To start demo configure data sources in secret.properties file.',
                'For H2 database it should be like following:',
                'dsH2.jdbc.url=jdbc:h2:tcp://localhost/mem:DemoDB;DB_CLOSE_DELAY=-1',
                'dsH2.jdbc.username=sa',
                'dsH2.jdbc.password=',
                ''
            );
        }
        else
            this.mainComment(sb);

        sb.startBlock(`public class ${clsName} {`);

        if (demo && shortFactoryCls)
            this.demoStartup(sb, cluster, shortFactoryCls);

        this.commentBlock(sb,
            'Start up node with specified configuration.',
            '',
            '@param args Command line arguments, none required.',
            '@throws Exception If failed.'
        );
        sb.startBlock('public static void main(String[] args) throws Exception {');

        if (demo) {
            sb.startBlock('try {');
            sb.append('// Start H2 database server.');
            sb.append('Server.createTcpServer("-tcpDaemon").start();');
            sb.endBlock('}');
            sb.startBlock('catch (SQLException ignore) {');
            sb.append('// No-op.');
            sb.endBlock('}');

            sb.emptyLine();
        }

        if ((nonEmpty(clientNearCaches) || demo) && shortFactoryCls) {
            imports.push('org.apache.ignite.Ignite');

            sb.append(`Ignite ignite = Ignition.start(${cfgRef});`);

            _.forEach(clientNearCaches, (cache, idx) => {
                sb.emptyLine();

                if (idx === 0)
                    sb.append('// Demo of near cache creation on client node.');

                const nearCacheMtd = this.javaTypes.toJavaName('nearConfiguration', cache.name);

                sb.append(`ignite.getOrCreateCache(${shortFactoryCls}.${this.javaTypes.toJavaName('cache', cache.name)}(), ${shortFactoryCls}.${nearCacheMtd}());`);
            });
        }
        else
            sb.append(`Ignition.start(${cfgRef});`);

        if (demo) {
            sb.emptyLine();

            sb.append('prepareDemoData();');

            sb.emptyLine();

            sb.append('runDemo(ignite);');
        }

        sb.endBlock('}');

        sb.endBlock('}');

        return sb.asString();
    }

    /**
     * Function to generate java class for load caches.
     *
     * @param caches Caches to load.
     * @param pkg Class package name.
     * @param clsName Class name.
     * @param {String} cfgRef Config.
     */
    static loadCaches(caches, pkg, clsName, cfgRef) {
        const sb = new StringBuilder();

        sb.append(`package ${pkg};`)
            .emptyLine();

        const imports = ['org.apache.ignite.Ignition', 'org.apache.ignite.Ignite'];

        _.forEach(this._prepareImports(imports), (cls) => sb.append(`import ${cls};`));
        sb.emptyLine();

        this.mainComment(sb);
        sb.startBlock(`public class ${clsName} {`);

        this.commentBlock(sb,
            '<p>',
            'Utility to load caches from database.',
            '<p>',
            'How to use:',
            '<ul>',
            '    <li>Start cluster.</li>',
            '    <li>Start this utility and wait while load complete.</li>',
            '</ul>',
            '',
            '@param args Command line arguments, none required.',
            '@throws Exception If failed.'
        );
        sb.startBlock('public static void main(String[] args) throws Exception {');

        sb.startBlock(`try (Ignite ignite = Ignition.start(${cfgRef})) {`);

        sb.append('System.out.println(">>> Loading caches...");');

        sb.emptyLine();

        _.forEach(caches, (cache) => {
            sb.append('System.out.println(">>> Loading cache: ' + cache.name + '");');
            sb.append('ignite.cache("' + cache.name + '").loadCache(null);');

            sb.emptyLine();
        });

        sb.append('System.out.println(">>> All caches loaded!");');

        sb.endBlock('}');

        sb.endBlock('}');

        sb.endBlock('}');

        return sb.asString();
    }

    /**
     * Checks if cluster has demo types.
     *
     * @param cluster Cluster to check.
     * @param demo Is demo enabled.
     * @returns {boolean} True if cluster has caches with demo types.
     */
    static isDemoConfigured(cluster, demo) {
        return demo && _.find(cluster.caches, (cache) => _.find(cache.domains, (domain) => _.find(PREDEFINED_QUERIES, (desc) => domain.valueType.toUpperCase().endsWith(desc.type))));
    }
}
