/*
 * 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))));
    }
}
