http://git-wip-us.apache.org/repos/asf/ignite/blob/087f6405/modules/web-console/frontend/app/modules/configuration/generator/Pom.service.js ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/modules/configuration/generator/Pom.service.js b/modules/web-console/frontend/app/modules/configuration/generator/Pom.service.js index f2d04b0..db58532 100644 --- a/modules/web-console/frontend/app/modules/configuration/generator/Pom.service.js +++ b/modules/web-console/frontend/app/modules/configuration/generator/Pom.service.js @@ -15,6 +15,8 @@ * limitations under the License. */ +import StringBuilder from './StringBuilder'; + // Java built-in class names. import POM_DEPENDENCIES from 'app/data/pom-dependencies.json'; @@ -29,8 +31,8 @@ class GeneratorPom { return s.replace(/[^A-Za-z0-9_\-.]+/g, '_'); } - addProperty(res, tag, val) { - res.line('<' + tag + '>' + val + '</' + tag + '>'); + addProperty(sb, tag, val) { + sb.append('<' + tag + '>' + val + '</' + tag + '>'); } addDependency(deps, groupId, artifactId, version, jar) { @@ -38,92 +40,89 @@ class GeneratorPom { deps.push({groupId, artifactId, version, jar}); } - addResource(res, dir, exclude) { - res.startBlock('<resource>'); + addResource(sb, dir, exclude) { + sb.startBlock('<resource>'); if (dir) - this.addProperty(res, 'directory', dir); + this.addProperty(sb, 'directory', dir); if (exclude) { - res.startBlock('<excludes>'); - this.addProperty(res, 'exclude', exclude); - res.endBlock('</excludes>'); + sb.startBlock('<excludes>'); + this.addProperty(sb, 'exclude', exclude); + sb.endBlock('</excludes>'); } - res.endBlock('</resource>'); + sb.endBlock('</resource>'); } - artifact(res, cluster, version) { - this.addProperty(res, 'groupId', 'org.apache.ignite'); - this.addProperty(res, 'artifactId', this.escapeId(cluster.name) + '-project'); - this.addProperty(res, 'version', version); + artifact(sb, cluster, version) { + this.addProperty(sb, 'groupId', 'org.apache.ignite'); + this.addProperty(sb, 'artifactId', this.escapeId(cluster.name) + '-project'); + this.addProperty(sb, 'version', version); - res.needEmptyLine = true; + sb.emptyLine(); } - dependencies(res, cluster, deps) { - if (!res) - res = $generatorCommon.builder(); - - res.startBlock('<dependencies>'); + dependencies(sb, cluster, deps) { + sb.startBlock('<dependencies>'); _.forEach(deps, (dep) => { - res.startBlock('<dependency>'); + sb.startBlock('<dependency>'); - this.addProperty(res, 'groupId', dep.groupId); - this.addProperty(res, 'artifactId', dep.artifactId); - this.addProperty(res, 'version', dep.version); + this.addProperty(sb, 'groupId', dep.groupId); + this.addProperty(sb, 'artifactId', dep.artifactId); + this.addProperty(sb, 'version', dep.version); if (dep.jar) { - this.addProperty(res, 'scope', 'system'); - this.addProperty(res, 'systemPath', '${project.basedir}/jdbc-drivers/' + dep.jar); + this.addProperty(sb, 'scope', 'system'); + this.addProperty(sb, 'systemPath', '${project.basedir}/jdbc-drivers/' + dep.jar); } - res.endBlock('</dependency>'); + sb.endBlock('</dependency>'); }); - res.endBlock('</dependencies>'); + sb.endBlock('</dependencies>'); - return res; + return sb; } - build(res, cluster, excludeGroupIds) { - res.startBlock('<build>'); - res.startBlock('<resources>'); - this.addResource(res, 'src/main/java', '**/*.java'); - this.addResource(res, 'src/main/resources'); - res.endBlock('</resources>'); - - res.startBlock('<plugins>'); - res.startBlock('<plugin>'); - this.addProperty(res, 'artifactId', 'maven-dependency-plugin'); - res.startBlock('<executions>'); - res.startBlock('<execution>'); - this.addProperty(res, 'id', 'copy-libs'); - this.addProperty(res, 'phase', 'test-compile'); - res.startBlock('<goals>'); - this.addProperty(res, 'goal', 'copy-dependencies'); - res.endBlock('</goals>'); - res.startBlock('<configuration>'); - this.addProperty(res, 'excludeGroupIds', excludeGroupIds.join(',')); - this.addProperty(res, 'outputDirectory', 'target/libs'); - this.addProperty(res, 'includeScope', 'compile'); - this.addProperty(res, 'excludeTransitive', 'true'); - res.endBlock('</configuration>'); - res.endBlock('</execution>'); - res.endBlock('</executions>'); - res.endBlock('</plugin>'); - res.startBlock('<plugin>'); - this.addProperty(res, 'artifactId', 'maven-compiler-plugin'); - this.addProperty(res, 'version', '3.1'); - res.startBlock('<configuration>'); - this.addProperty(res, 'source', '1.7'); - this.addProperty(res, 'target', '1.7'); - res.endBlock('</configuration>'); - res.endBlock('</plugin>'); - res.endBlock('</plugins>'); - res.endBlock('</build>'); - - res.endBlock('</project>'); + build(sb = new StringBuilder(), cluster, excludeGroupIds) { + sb.startBlock('<build>'); + sb.startBlock('<resources>'); + this.addResource(sb, 'src/main/java', '**/*.java'); + this.addResource(sb, 'src/main/resources'); + sb.endBlock('</resources>'); + + sb.startBlock('<plugins>'); + sb.startBlock('<plugin>'); + this.addProperty(sb, 'artifactId', 'maven-dependency-plugin'); + sb.startBlock('<executions>'); + sb.startBlock('<execution>'); + this.addProperty(sb, 'id', 'copy-libs'); + this.addProperty(sb, 'phase', 'test-compile'); + sb.startBlock('<goals>'); + this.addProperty(sb, 'goal', 'copy-dependencies'); + sb.endBlock('</goals>'); + sb.startBlock('<configuration>'); + this.addProperty(sb, 'excludeGroupIds', excludeGroupIds.join(',')); + this.addProperty(sb, 'outputDirectory', 'target/libs'); + this.addProperty(sb, 'includeScope', 'compile'); + this.addProperty(sb, 'excludeTransitive', 'true'); + sb.endBlock('</configuration>'); + sb.endBlock('</execution>'); + sb.endBlock('</executions>'); + sb.endBlock('</plugin>'); + sb.startBlock('<plugin>'); + this.addProperty(sb, 'artifactId', 'maven-compiler-plugin'); + this.addProperty(sb, 'version', '3.1'); + sb.startBlock('<configuration>'); + this.addProperty(sb, 'source', '1.7'); + this.addProperty(sb, 'target', '1.7'); + sb.endBlock('</configuration>'); + sb.endBlock('</plugin>'); + sb.endBlock('</plugins>'); + sb.endBlock('</build>'); + + sb.endBlock('</project>'); } /** @@ -144,10 +143,10 @@ class GeneratorPom { * * @param cluster Cluster to take info about dependencies. * @param version Ignite version for Ignite dependencies. - * @param res Resulting output with generated pom. + * @param sb Resulting output with generated pom. * @returns {string} Generated content. */ - generate(cluster, version, res) { + generate(cluster, version, sb = new StringBuilder()) { const caches = cluster.caches; const deps = []; const storeDeps = []; @@ -155,9 +154,6 @@ class GeneratorPom { const blobStoreFactory = {cacheStoreFactory: {kind: 'CacheHibernateBlobStoreFactory'}}; - if (!res) - res = $generatorCommon.builder(); - _.forEach(caches, (cache) => { if (cache.cacheStoreFactory && cache.cacheStoreFactory.kind) this.storeFactoryDependency(storeDeps, cache.cacheStoreFactory[cache.cacheStoreFactory.kind]); @@ -166,21 +162,21 @@ class GeneratorPom { this.addDependency(deps, 'org.apache.ignite', 'ignite-extdata-p2p', version); }); - res.line('<?xml version="1.0" encoding="UTF-8"?>'); + sb.append('<?xml version="1.0" encoding="UTF-8"?>'); - res.needEmptyLine = true; + sb.emptyLine(); - res.line('<!-- ' + $generatorCommon.mainComment('Maven project') + ' -->'); + sb.append(`<!-- ${sb.generatedBy()} -->`); - res.needEmptyLine = true; + sb.emptyLine(); - res.startBlock('<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">'); + sb.startBlock('<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">'); - res.line('<modelVersion>4.0.0</modelVersion>'); + sb.append('<modelVersion>4.0.0</modelVersion>'); - res.needEmptyLine = true; + sb.emptyLine(); - this.artifact(res, cluster, version); + this.artifact(sb, cluster, version); this.addDependency(deps, 'org.apache.ignite', 'ignite-core', version); @@ -200,6 +196,17 @@ class GeneratorPom { this.storeFactoryDependency(storeDeps, cluster.discovery.Jdbc); } + _.forEach(cluster.checkpointSpi, (spi) => { + if (spi.kind === 'S3') { + dep = POM_DEPENDENCIES.S3; + + if (dep) + this.addDependency(deps, 'org.apache.ignite', dep.artifactId, version); + } + else if (spi.kind === 'JDBC') + this.storeFactoryDependency(storeDeps, spi.JDBC); + }); + if (_.find(cluster.igfss, (igfs) => igfs.secondaryFileSystemEnabled)) this.addDependency(deps, 'org.apache.ignite', 'ignite-hadoop', version); @@ -213,13 +220,13 @@ class GeneratorPom { this.addDependency(deps, 'org.apache.ignite', dep.artifactId, version); } - this.dependencies(res, cluster, deps.concat(storeDeps)); + this.dependencies(sb, cluster, deps.concat(storeDeps)); - res.needEmptyLine = true; + sb.emptyLine(); - this.build(res, cluster, excludeGroupIds); + this.build(sb, cluster, excludeGroupIds); - return res; + return sb; } }
http://git-wip-us.apache.org/repos/asf/ignite/blob/087f6405/modules/web-console/frontend/app/modules/configuration/generator/Properties.service.js ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/modules/configuration/generator/Properties.service.js b/modules/web-console/frontend/app/modules/configuration/generator/Properties.service.js new file mode 100644 index 0000000..07f8dff --- /dev/null +++ b/modules/web-console/frontend/app/modules/configuration/generator/Properties.service.js @@ -0,0 +1,74 @@ +/* + * 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 StringBuilder from './StringBuilder'; + +/** + * Properties generation entry point. + */ +export default class PropertiesGenerator { + _collectProperties(bean) { + const props = []; + + _.forEach(bean.properties, (prop) => { + switch (prop.clsName) { + case 'DATA_SOURCE': + props.push(...this._collectProperties(prop.value)); + props.push(''); + + break; + case 'BEAN': + props.push(...this._collectProperties(prop.value)); + + break; + case 'PROPERTY': + case 'PROPERTY_CHAR': + props.push(`${prop.value}=${prop.hint}`); + + break; + case 'ARRAY': + case 'COLLECTION': + _.forEach(prop.items, (item) => { + const itemLines = this._collectProperties(item); + + if (_.intersection(props, itemLines).length !== itemLines.length) + props.push(...this._collectProperties(item)); + }); + + break; + default: + } + }); + + return props; + } + + generate(cfg) { + const lines = this._collectProperties(cfg); + + if (_.isEmpty(lines)) + return null; + + const sb = new StringBuilder(); + + sb.append(`# ${sb.generatedBy()}`); + + _.forEach(lines, (line) => sb.append(line)); + + return sb.asString(); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/087f6405/modules/web-console/frontend/app/modules/configuration/generator/Readme.service.js ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/modules/configuration/generator/Readme.service.js b/modules/web-console/frontend/app/modules/configuration/generator/Readme.service.js new file mode 100644 index 0000000..7043807 --- /dev/null +++ b/modules/web-console/frontend/app/modules/configuration/generator/Readme.service.js @@ -0,0 +1,79 @@ +/* + * 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 StringBuilder from './StringBuilder'; + +/** + * Properties generation entry point. + */ +export default class ReadmeGenerator { + header(sb) { + sb.append('Content of this folder was generated by Apache Ignite Web Console'); + sb.append('================================================================='); + } + + /** + * Generate README.txt for jdbc folder. + * + * @param sb Resulting output with generated readme. + * @returns {string} Generated content. + */ + generateJDBC(sb = new StringBuilder()) { + sb.append('Proprietary JDBC drivers for databases like Oracle, IBM DB2, Microsoft SQL Server are not available on Maven Central repository.'); + sb.append('Drivers should be downloaded manually and copied to this folder.'); + + return sb.asString(); + } + + /** + * Generate README.txt. + * + * @returns {string} Generated content. + */ + generate(sb = new StringBuilder()) { + this.header(sb); + sb.emptyLine(); + + sb.append('Project structure:'); + sb.append(' /config - this folder contains client and server XML configurations.'); + sb.append(' /jdbc-drivers - this folder should contains proprietary JDBC drivers.'); + sb.append(' /src - this folder contains generated java code.'); + sb.append(' /src/main/java/config - this folder contains generated java classes with cluster configuration from code.'); + sb.append(' /src/main/java/startup - this folder contains generated java classes with server and client nodes startup code.'); + sb.append(' /src/main/java/[model] - this optional folder will be named as package name for your POJO classes and contain generated POJO files.'); + sb.append(' /src/main/resources - this optional folder contains generated secret.properties file with security sensitive information if any.'); + sb.append(' Dockerfile - sample Docker file. With this file you could package Ignite deployment with all the dependencies into a standard container.'); + sb.append(' pom.xml - generated Maven project description, could be used to open generated project in IDE or build with Maven.'); + sb.append(' README.txt - this file.'); + + sb.emptyLine(); + + sb.append('Ignite ships with CacheJdbcPojoStore, which is out-of-the-box JDBC implementation of the IgniteCacheStore '); + sb.append('interface, and automatically handles all the write-through and read-through logic.'); + + sb.emptyLine(); + + sb.append('You can use generated configuration and POJO classes as part of your application.'); + + sb.emptyLine(); + + sb.append('Note, in case of using proprietary JDBC drivers (Oracle, IBM DB2, Microsoft SQL Server)'); + sb.append('you should download them manually and copy into ./jdbc-drivers folder.'); + + return sb.asString(); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/087f6405/modules/web-console/frontend/app/modules/configuration/generator/SharpTransformer.service.js ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/modules/configuration/generator/SharpTransformer.service.js b/modules/web-console/frontend/app/modules/configuration/generator/SharpTransformer.service.js new file mode 100644 index 0000000..19043f6 --- /dev/null +++ b/modules/web-console/frontend/app/modules/configuration/generator/SharpTransformer.service.js @@ -0,0 +1,243 @@ +/* + * 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 _ from 'lodash'; +import AbstractTransformer from './AbstractTransformer'; +import StringBuilder from './StringBuilder'; + +export default ['JavaTypes', 'IgnitePlatformGenerator', (JavaTypes, generator) => { + return class SharpTransformer extends AbstractTransformer { + static generator = generator; + + static commentBlock(sb, ...lines) { + _.forEach(lines, (line) => sb.append(`// ${line}`)); + } + + static doc(sb, ...lines) { + sb.append('/// <summary>'); + _.forEach(lines, (line) => sb.append(`/// ${line}`)); + sb.append('/// </summary>'); + } + + static mainComment(sb) { + return this.doc(sb, sb.generatedBy()); + } + + /** + * + * @param {Array.<String>} sb + * @param {Bean} bean + */ + static _defineBean(sb, bean) { + const shortClsName = JavaTypes.shortClassName(bean.clsName); + + sb.append(`var ${bean.id} = new ${shortClsName}();`); + } + + /** + * @param {StringBuilder} sb + * @param {Bean} parent + * @param {Bean} propertyName + * @param {String|Bean} value + * @private + */ + static _setProperty(sb, parent, propertyName, value) { + sb.append(`${parent.id}.${_.upperFirst(propertyName)} = ${value};`); + } + + /** + * + * @param {StringBuilder} sb + * @param {Bean} parent + * @param {String} propertyName + * @param {Bean} bean + * @private + */ + static _setBeanProperty(sb, parent, propertyName, bean) { + sb.append(`${parent.id}.${_.upperFirst(propertyName)} = ${bean.id};`); + } + + static _toObject(clsName, val) { + const items = _.isArray(val) ? val : [val]; + + return _.map(items, (item, idx) => { + if (_.isNil(item)) + return 'null'; + + const shortClsName = JavaTypes.shortClassName(clsName); + + switch (shortClsName) { + // case 'byte': + // return `(byte) ${item}`; + // case 'Serializable': + case 'String': + if (items.length > 1) + return `"${item}"${idx !== items.length - 1 ? ' +' : ''}`; + + return `"${item}"`; + // case 'Path': + // return `"${item.replace(/\\/g, '\\\\')}"`; + // case 'Class': + // return `${this.shortClassName(item)}.class`; + // case 'UUID': + // return `UUID.fromString("${item}")`; + // case 'PropertyChar': + // return `props.getProperty("${item}").toCharArray()`; + // case 'Property': + // return `props.getProperty("${item}")`; + // case 'Bean': + // if (item.isComplex()) + // return item.id; + // + // return this._newBean(item); + default: + if (JavaTypes.nonEnum(shortClsName)) + return item; + + return `${shortClsName}.${item}`; + } + }); + } + + /** + * + * @param {StringBuilder} sb + * @param {Bean} bean + * @returns {Array} + */ + static _setProperties(sb = new StringBuilder(), bean) { + _.forEach(bean.properties, (prop) => { + switch (prop.clsName) { + case 'ICollection': + // const implClsName = JavaTypes.shortClassName(prop.implClsName); + + const colTypeClsName = JavaTypes.shortClassName(prop.typeClsName); + + if (colTypeClsName === 'String') { + const items = this._toObject(colTypeClsName, prop.items); + + sb.append(`${bean.id}.${_.upperFirst(prop.name)} = new {${items.join(', ')}};`); + } + // else { + // if (_.includes(vars, prop.id)) + // sb.append(`${prop.id} = new ${implClsName}<>();`); + // else { + // vars.push(prop.id); + // + // sb.append(`${clsName}<${colTypeClsName}> ${prop.id} = new ${implClsName}<>();`); + // } + // + // sb.emptyLine(); + // + // if (nonBean) { + // const items = this._toObject(colTypeClsName, prop.items); + // + // _.forEach(items, (item) => { + // 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, bean.id, prop.name, prop.id); + // } + // } + + break; + + case 'Bean': + const nestedBean = prop.value; + + this._defineBean(sb, nestedBean); + + sb.emptyLine(); + + this._setProperties(sb, nestedBean); + + sb.emptyLine(); + + this._setBeanProperty(sb, bean, prop.name, nestedBean); + + break; + default: + this._setProperty(sb, bean, prop.name, this._toObject(prop.clsName, prop.value)); + } + }); + + return sb; + } + + /** + * Build Java startup class with configuration. + * + * @param {Bean} cfg + * @param pkg Package name. + * @param clsName Class name for generate factory class otherwise generate code snippet. + * @param clientNearCfg Optional near cache configuration for client node. + * @returns {String} + */ + static toClassFile(cfg, pkg, clsName) { + const sb = new StringBuilder(); + + sb.startBlock(`namespace ${pkg}`, '{'); + + _.forEach(_.sortBy(cfg.collectClasses()), (cls) => sb.append(`using ${cls};`)); + sb.emptyLine(); + + + this.mainComment(sb); + sb.startBlock(`public class ${clsName}`, '{'); + + this.doc(sb, 'Configure grid.'); + sb.startBlock('public static IgniteConfiguration CreateConfiguration()', '{'); + + this._defineBean(sb, cfg); + + sb.emptyLine(); + + this._setProperties(sb, cfg); + + sb.emptyLine(); + + sb.append(`return ${cfg.id};`); + + sb.endBlock('}'); + + sb.endBlock('}'); + + sb.endBlock('}'); + + return sb.asString(); + } + + static generateSection(bean) { + const sb = new StringBuilder(); + + this._setProperties(sb, bean); + + return sb.asString(); + } + }; +}]; http://git-wip-us.apache.org/repos/asf/ignite/blob/087f6405/modules/web-console/frontend/app/modules/configuration/generator/SpringTransformer.service.js ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/modules/configuration/generator/SpringTransformer.service.js b/modules/web-console/frontend/app/modules/configuration/generator/SpringTransformer.service.js new file mode 100644 index 0000000..91a85fa --- /dev/null +++ b/modules/web-console/frontend/app/modules/configuration/generator/SpringTransformer.service.js @@ -0,0 +1,325 @@ +/* + * 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 _ from 'lodash'; + +import AbstractTransformer from './AbstractTransformer'; +import StringBuilder from './StringBuilder'; + +export default ['JavaTypes', 'igniteEventGroups', 'IgniteConfigurationGenerator', (JavaTypes, eventGroups, generator) => { + return class SpringTransformer extends AbstractTransformer { + static generator = generator; + + static commentBlock(sb, ...lines) { + if (lines.length > 1) { + sb.append('<!--'); + + _.forEach(lines, (line) => sb.append(` ${line}`)); + + sb.append('-->'); + } + else + sb.append(`<!-- ${_.head(lines)} -->`); + } + + static appendBean(sb, bean, appendId) { + const beanTags = []; + + if (appendId) + beanTags.push(`id="${bean.id}"`); + + beanTags.push(`class="${bean.clsName}"`); + + if (bean.factoryMtd) + beanTags.push(`factory-method="${bean.factoryMtd}"`); + + sb.startBlock(`<bean ${beanTags.join(' ')}>`); + + _.forEach(bean.arguments, (arg) => { + if (arg.clsName === 'MAP') { + sb.startBlock('<constructor-arg>'); + this._constructMap(sb, arg); + sb.endBlock('</constructor-arg>'); + } + else if (_.isNil(arg.value)) { + sb.startBlock('<constructor-arg>'); + sb.append('<null/>'); + sb.endBlock('</constructor-arg>'); + } + else if (arg.constant) { + sb.startBlock('<constructor-arg>'); + sb.append(`<util:constant static-field="${arg.clsName}.${arg.value}"/>`); + sb.endBlock('</constructor-arg>'); + } + else if (arg.clsName === 'BEAN') { + sb.startBlock('<constructor-arg>'); + this.appendBean(sb, arg.value); + sb.endBlock('</constructor-arg>'); + } + else + sb.append(`<constructor-arg value="${this._toObject(arg.clsName, arg.value)}"/>`); + }); + + this._setProperties(sb, bean); + + sb.endBlock('</bean>'); + } + + static _toObject(clsName, items) { + return _.map(_.isArray(items) ? items : [items], (item) => { + switch (clsName) { + case 'PROPERTY': + case 'PROPERTY_CHAR': + return `\${${item}}`; + case 'java.lang.Class': + return JavaTypes.fullClassName(item); + case 'long': + return `${item}L`; + default: + return item; + } + }); + } + + static _isBean(clsName) { + return JavaTypes.nonBuiltInClass(clsName) && JavaTypes.nonEnum(clsName) && _.includes(clsName, '.'); + } + + static _setCollection(sb, prop, tag) { + sb.startBlock(`<property name="${prop.name}">`); + sb.startBlock(`<${tag}>`); + + _.forEach(prop.items, (item, idx) => { + if (this._isBean(prop.typeClsName)) { + if (idx !== 0) + sb.emptyLine(); + + this.appendBean(sb, item); + } + else + sb.append(`<value>${item}</value>`); + }); + + sb.endBlock(`</${tag}>`); + sb.endBlock('</property>'); + } + + static _constructMap(sb, map) { + sb.startBlock('<map>'); + + _.forEach(map.entries, (entry) => { + const key = entry[map.keyField]; + const val = entry[map.valField]; + + const isKeyBean = this._isBean(map.keyClsName); + const isValBean = this._isBean(map.valClsName); + + + if (isKeyBean || isValBean) { + sb.startBlock('<entry>'); + + sb.startBlock('<key>'); + if (isKeyBean) + this.appendBean(sb, key); + else + sb.append(this._toObject(map.keyClsName, key)); + sb.endBlock('</key>'); + + sb.startBlock('<value>'); + if (isValBean) + this.appendBean(sb, val); + else + sb.append(this._toObject(map.valClsName, val)); + sb.endBlock('</value>'); + + sb.endBlock('</entry>'); + } + else + sb.append(`<entry key="${this._toObject(map.keyClsName, key)}" value="${this._toObject(map.valClsName, val)}"/>`); + }); + + sb.endBlock('</map>'); + } + + /** + * + * @param {StringBuilder} sb + * @param {Bean} bean + * @returns {StringBuilder} + */ + static _setProperties(sb, bean) { + _.forEach(bean.properties, (prop, idx) => { + switch (prop.clsName) { + case 'DATA_SOURCE': + const valAttr = prop.name === 'dataSource' ? 'ref' : 'value'; + + sb.append(`<property name="${prop.name}" ${valAttr}="${prop.id}"/>`); + + break; + case 'EVENT_TYPES': + sb.startBlock(`<property name="${prop.name}">`); + + if (prop.eventTypes.length === 1) { + const evtGrp = _.find(eventGroups, {value: _.head(prop.eventTypes)}); + + evtGrp && sb.append(`<util:constant static-field="${evtGrp.class}.${evtGrp.value}"/>`); + } + else { + sb.startBlock('<list>'); + + _.forEach(prop.eventTypes, (item, ix) => { + ix > 0 && sb.emptyLine(); + + const evtGrp = _.find(eventGroups, {value: item}); + + if (evtGrp) { + sb.append(`<!-- EventType.${item} -->`); + + _.forEach(evtGrp.events, (event) => + sb.append(`<util:constant static-field="${evtGrp.class}.${event}"/>`)); + } + }); + + sb.endBlock('</list>'); + } + + sb.endBlock('</property>'); + + break; + case 'ARRAY': + this._setCollection(sb, prop, 'array'); + + break; + case 'COLLECTION': + this._setCollection(sb, prop, 'list'); + + break; + case 'MAP': + sb.startBlock(`<property name="${prop.name}">`); + + this._constructMap(sb, prop); + + sb.endBlock('</property>'); + + break; + case 'java.util.Properties': + sb.startBlock(`<property name="${prop.name}">`); + sb.startBlock('<props>'); + + _.forEach(prop.entries, (entry) => { + sb.append(`<prop key="${entry.name}">${entry.value}</prop>`); + }); + + sb.endBlock('</props>'); + sb.endBlock('</property>'); + + break; + case 'BEAN': + sb.startBlock(`<property name="${prop.name}">`); + + this.appendBean(sb, prop.value); + + sb.endBlock('</property>'); + + break; + default: + sb.append(`<property name="${prop.name}" value="${this._toObject(prop.clsName, prop.value)}"/>`); + } + + this._emptyLineIfNeeded(sb, bean.properties, idx); + }); + + return sb; + } + + /** + * Build final XML. + * + * @param {Bean} cfg Ignite configuration. + * @param {Boolean} clientNearCaches + * @returns {StringBuilder} + */ + static igniteConfiguration(cfg, clientNearCaches) { + const sb = new StringBuilder(); + + // 0. Add header. + sb.append('<?xml version="1.0" encoding="UTF-8"?>'); + sb.emptyLine(); + + this.mainComment(sb); + sb.emptyLine(); + + // 1. Start beans section. + sb.startBlock([ + '<beans xmlns="http://www.springframework.org/schema/beans"', + ' xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"', + ' xmlns:util="http://www.springframework.org/schema/util"', + ' xsi:schemaLocation="http://www.springframework.org/schema/beans', + ' http://www.springframework.org/schema/beans/spring-beans.xsd', + ' http://www.springframework.org/schema/util', + ' http://www.springframework.org/schema/util/spring-util.xsd">']); + + // 2. Add external property file + if (this.hasProperties(cfg)) { + this.commentBlock(sb, 'Load external properties file.'); + + sb.startBlock('<bean id="placeholderConfig" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">'); + sb.append('<property name="location" value="classpath:secret.properties"/>'); + sb.endBlock('</bean>'); + + sb.emptyLine(); + } + + // 3. Add data sources. + const dataSources = this.collectDataSources(cfg); + + if (dataSources.length) { + this.commentBlock(sb, 'Data source beans will be initialized from external properties file.'); + + _.forEach(dataSources, (ds) => { + this.appendBean(sb, ds, true); + + sb.emptyLine(); + }); + } + + _.forEach(clientNearCaches, (cache) => { + this.commentBlock(sb, 'Configuration of near cache for cache "' + cache.name + '"'); + + this.appendBean(sb, generator.cacheNearClient(cache), true); + + sb.emptyLine(); + }); + + // 3. Add main content. + this.appendBean(sb, cfg); + + // 4. Close beans section. + sb.endBlock('</beans>'); + + return sb; + } + + static cluster(cluster, client) { + const cfg = generator.igniteConfiguration(cluster, client); + + const clientNearCaches = client ? _.filter(cluster.caches, (cache) => _.get(cache, 'clientNearConfiguration.enabled')) : []; + + return this.igniteConfiguration(cfg, clientNearCaches); + } + }; +}]; http://git-wip-us.apache.org/repos/asf/ignite/blob/087f6405/modules/web-console/frontend/app/modules/configuration/generator/StringBuilder.js ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/modules/configuration/generator/StringBuilder.js b/modules/web-console/frontend/app/modules/configuration/generator/StringBuilder.js new file mode 100644 index 0000000..338bf1e --- /dev/null +++ b/modules/web-console/frontend/app/modules/configuration/generator/StringBuilder.js @@ -0,0 +1,76 @@ +/* + * 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. + */ + +const DATE_OPTS = { + month: '2-digit', + day: '2-digit', + year: 'numeric', + hour: '2-digit', + minute: '2-digit', + hour12: false +}; + +export default class StringBuilder { + generatedBy() { + return `This file was generated by Ignite Web Console (${new Date().toLocaleString('en-US', DATE_OPTS)})`; + } + + /** + * @param deep + * @param indent + */ + constructor(deep = 0, indent = 4) { + this.indent = indent; + this.deep = deep; + this.lines = []; + } + + emptyLine() { + this.lines.push(''); + + return this; + } + + append(lines) { + if (_.isArray(lines)) + _.forEach(lines, (line) => this.lines.push(_.repeat(' ', this.indent * this.deep) + line)); + else + this.lines.push(_.repeat(' ', this.indent * this.deep) + lines); + + return this; + } + + startBlock(lines) { + this.append(lines); + + this.deep++; + + return this; + } + + endBlock(line) { + this.deep--; + + this.append(line); + + return this; + } + + asString() { + return this.lines.join('\n'); + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/087f6405/modules/web-console/frontend/app/modules/configuration/generator/Xml.service.js ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/modules/configuration/generator/Xml.service.js b/modules/web-console/frontend/app/modules/configuration/generator/Xml.service.js deleted file mode 100644 index 58d1ce0..0000000 --- a/modules/web-console/frontend/app/modules/configuration/generator/Xml.service.js +++ /dev/null @@ -1,21 +0,0 @@ -/* - * 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. - */ - -// TODO IGNITE-2052: need move $generatorXml to services. -export default ['GeneratorXml', () => { - return $generatorXml; -}]; http://git-wip-us.apache.org/repos/asf/ignite/blob/087f6405/modules/web-console/frontend/app/modules/configuration/generator/defaults/cache.platform.provider.js ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/modules/configuration/generator/defaults/cache.platform.provider.js b/modules/web-console/frontend/app/modules/configuration/generator/defaults/cache.platform.provider.js new file mode 100644 index 0000000..f06e11b --- /dev/null +++ b/modules/web-console/frontend/app/modules/configuration/generator/defaults/cache.platform.provider.js @@ -0,0 +1,60 @@ +/* + * 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 _ from 'lodash'; + +const enumValueMapper = (val) => _.capitalize(val); + +const DFLT_CACHE = { + cacheMode: { + clsName: 'Apache.Ignite.Core.Cache.Configuration.CacheMode', + mapper: enumValueMapper + }, + atomicityMode: { + clsName: 'Apache.Ignite.Core.Cache.Configuration.CacheAtomicityMode', + mapper: enumValueMapper + }, + memoryMode: { + clsName: 'Apache.Ignite.Core.Cache.Configuration.CacheMemoryMode', + value: 'ONHEAP_TIERED', + mapper: enumValueMapper + }, + atomicWriteOrderMode: { + clsName: 'org.apache.ignite.cache.CacheAtomicWriteOrderMode', + mapper: enumValueMapper + }, + writeSynchronizationMode: { + clsName: 'org.apache.ignite.cache.CacheWriteSynchronizationMode', + value: 'PRIMARY_SYNC', + mapper: enumValueMapper + }, + rebalanceMode: { + clsName: 'org.apache.ignite.cache.CacheRebalanceMode', + value: 'ASYNC', + mapper: enumValueMapper + } +}; + +export default function() { + this.append = (dflts) => { + _.merge(DFLT_CACHE, dflts); + }; + + this.$get = ['igniteCacheDefaults', (cacheDefaults) => { + return _.merge({}, cacheDefaults, DFLT_CACHE); + }]; +} http://git-wip-us.apache.org/repos/asf/ignite/blob/087f6405/modules/web-console/frontend/app/modules/configuration/generator/defaults/cache.provider.js ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/modules/configuration/generator/defaults/cache.provider.js b/modules/web-console/frontend/app/modules/configuration/generator/defaults/cache.provider.js new file mode 100644 index 0000000..5ff1e02 --- /dev/null +++ b/modules/web-console/frontend/app/modules/configuration/generator/defaults/cache.provider.js @@ -0,0 +1,129 @@ +/* + * 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 _ from 'lodash'; + +const DFLT_CACHE = { + cacheMode: { + clsName: 'org.apache.ignite.cache.CacheMode' + }, + atomicityMode: { + clsName: 'org.apache.ignite.cache.CacheAtomicityMode' + }, + memoryMode: { + clsName: 'org.apache.ignite.cache.CacheMemoryMode', + value: 'ONHEAP_TIERED' + }, + offHeapMaxMemory: -1, + startSize: 1500000, + swapEnabled: false, + sqlOnheapRowCacheSize: 10240, + longQueryWarningTimeout: 3000, + snapshotableIndex: false, + sqlEscapeAll: false, + storeKeepBinary: false, + loadPreviousValue: false, + readThrough: false, + writeThrough: false, + writeBehindEnabled: false, + writeBehindBatchSize: 512, + writeBehindFlushSize: 10240, + writeBehindFlushFrequency: 5000, + writeBehindFlushThreadCount: 1, + maxConcurrentAsyncOperations: 500, + defaultLockTimeout: 0, + atomicWriteOrderMode: { + clsName: 'org.apache.ignite.cache.CacheAtomicWriteOrderMode' + }, + writeSynchronizationMode: { + clsName: 'org.apache.ignite.cache.CacheWriteSynchronizationMode', + value: 'PRIMARY_SYNC' + }, + rebalanceMode: { + clsName: 'org.apache.ignite.cache.CacheRebalanceMode', + value: 'ASYNC' + }, + rebalanceThreadPoolSize: 1, + rebalanceBatchSize: 524288, + rebalanceBatchesPrefetchCount: 2, + rebalanceOrder: 0, + rebalanceDelay: 0, + rebalanceTimeout: 10000, + rebalanceThrottle: 0, + statisticsEnabled: false, + managementEnabled: false, + nearConfiguration: { + nearStartSize: 375000 + }, + clientNearConfiguration: { + nearStartSize: 375000 + }, + evictionPolicy: { + LRU: { + batchSize: 1, + maxSize: 100000 + }, + FIFO: { + batchSize: 1, + maxSize: 100000 + }, + SORTED: { + batchSize: 1, + maxSize: 100000 + } + }, + queryMetadata: 'Configuration', + fields: { + keyClsName: 'java.lang.String', + valClsName: 'java.lang.String', + valField: 'className', + entries: [] + }, + aliases: { + keyClsName: 'java.lang.String', + valClsName: 'java.lang.String', + keyField: 'field', + valField: 'alias', + entries: [] + }, + indexes: { + indexType: { + clsName: 'org.apache.ignite.cache.QueryIndexType' + }, + fields: { + keyClsName: 'java.lang.String', + valClsName: 'java.lang.Boolean', + valField: 'direction', + entries: [] + } + }, + typeField: { + databaseFieldType: { + clsName: 'java.sql.Types' + } + } +}; + +export default function() { + this.append = (dflts) => { + _.merge(DFLT_CACHE, dflts); + }; + + this.$get = [() => { + return DFLT_CACHE; + }]; +} http://git-wip-us.apache.org/repos/asf/ignite/blob/087f6405/modules/web-console/frontend/app/modules/configuration/generator/defaults/cluster.platform.provider.js ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/modules/configuration/generator/defaults/cluster.platform.provider.js b/modules/web-console/frontend/app/modules/configuration/generator/defaults/cluster.platform.provider.js new file mode 100644 index 0000000..582426e --- /dev/null +++ b/modules/web-console/frontend/app/modules/configuration/generator/defaults/cluster.platform.provider.js @@ -0,0 +1,49 @@ +/* + * 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 _ from 'lodash'; + +const enumValueMapper = (val) => _.capitalize(val); + +const DFLT_CLUSTER = { + atomics: { + cacheMode: { + clsName: 'Apache.Ignite.Core.Cache.Configuration.CacheMode', + mapper: enumValueMapper + } + }, + transactionConfiguration: { + defaultTxConcurrency: { + clsName: 'Apache.Ignite.Core.Transactions.TransactionConcurrency', + mapper: enumValueMapper + }, + defaultTxIsolation: { + clsName: 'Apache.Ignite.Core.Transactions.TransactionIsolation', + mapper: enumValueMapper + } + } +}; + +export default function() { + this.append = (dflts) => { + _.merge(DFLT_CLUSTER, dflts); + }; + + this.$get = ['igniteClusterDefaults', (clusterDefaults) => { + return _.merge({}, clusterDefaults, DFLT_CLUSTER); + }]; +} http://git-wip-us.apache.org/repos/asf/ignite/blob/087f6405/modules/web-console/frontend/app/modules/configuration/generator/defaults/cluster.provider.js ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/modules/configuration/generator/defaults/cluster.provider.js b/modules/web-console/frontend/app/modules/configuration/generator/defaults/cluster.provider.js new file mode 100644 index 0000000..1be4b70 --- /dev/null +++ b/modules/web-console/frontend/app/modules/configuration/generator/defaults/cluster.provider.js @@ -0,0 +1,293 @@ +/* + * 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. + */ + +const DFLT_CLUSTER = { + localHost: '0.0.0.0', + discovery: { + localPort: 47500, + localPortRange: 100, + socketTimeout: 5000, + ackTimeout: 5000, + maxAckTimeout: 600000, + networkTimeout: 5000, + joinTimeout: 0, + threadPriority: 10, + heartbeatFrequency: 2000, + maxMissedHeartbeats: 1, + maxMissedClientHeartbeats: 5, + topHistorySize: 1000, + reconnectCount: 10, + statisticsPrintFrequency: 0, + ipFinderCleanFrequency: 60000, + forceServerMode: false, + clientReconnectDisabled: false, + Multicast: { + multicastGroup: '228.1.2.4', + multicastPort: 47400, + responseWaitTime: 500, + addressRequestAttempts: 2, + localAddress: '0.0.0.0' + }, + Jdbc: { + initSchema: false + }, + SharedFs: { + path: 'disco/tcp' + }, + ZooKeeper: { + basePath: '/services', + serviceName: 'ignite', + allowDuplicateRegistrations: false, + ExponentialBackoff: { + baseSleepTimeMs: 1000, + maxRetries: 10 + }, + BoundedExponentialBackoffRetry: { + baseSleepTimeMs: 1000, + maxSleepTimeMs: 2147483647, + maxRetries: 10 + }, + UntilElapsed: { + maxElapsedTimeMs: 60000, + sleepMsBetweenRetries: 1000 + }, + RetryNTimes: { + n: 10, + sleepMsBetweenRetries: 1000 + }, + OneTime: { + sleepMsBetweenRetry: 1000 + }, + Forever: { + retryIntervalMs: 1000 + } + } + }, + atomics: { + atomicSequenceReserveSize: 1000, + backups: 0, + cacheMode: { + clsName: 'org.apache.ignite.cache.CacheMode', + value: 'PARTITIONED' + } + }, + binary: { + compactFooter: true, + typeConfigurations: { + enum: false + } + }, + collision: { + kind: null, + JobStealing: { + activeJobsThreshold: 95, + waitJobsThreshold: 0, + messageExpireTime: 1000, + maximumStealingAttempts: 5, + stealingEnabled: true, + stealingAttributes: { + keyClsName: 'java.lang.String', + valClsName: 'java.io.Serializable', + items: [] + } + }, + PriorityQueue: { + priorityAttributeKey: 'grid.task.priority', + jobPriorityAttributeKey: 'grid.job.priority', + defaultPriority: 0, + starvationIncrement: 1, + starvationPreventionEnabled: true + } + }, + communication: { + localPort: 47100, + localPortRange: 100, + sharedMemoryPort: 48100, + directBuffer: false, + directSendBuffer: false, + idleConnectionTimeout: 30000, + connectTimeout: 5000, + maxConnectTimeout: 600000, + reconnectCount: 10, + socketSendBuffer: 32768, + socketReceiveBuffer: 32768, + messageQueueLimit: 1024, + tcpNoDelay: true, + ackSendThreshold: 16, + unacknowledgedMessagesBufferSize: 0, + socketWriteTimeout: 2000 + }, + networkTimeout: 5000, + networkSendRetryDelay: 1000, + networkSendRetryCount: 3, + discoveryStartupDelay: 60000, + connector: { + port: 11211, + portRange: 100, + idleTimeout: 7000, + idleQueryCursorTimeout: 600000, + idleQueryCursorCheckFrequency: 60000, + receiveBufferSize: 32768, + sendBufferSize: 32768, + sendQueueLimit: 0, + directBuffer: false, + noDelay: true, + sslEnabled: false, + sslClientAuth: false + }, + deploymentMode: { + clsName: 'org.apache.ignite.configuration.DeploymentMode', + value: 'SHARED' + }, + peerClassLoadingEnabled: false, + peerClassLoadingMissedResourcesCacheSize: 100, + peerClassLoadingThreadPoolSize: 2, + failoverSpi: { + JobStealing: { + maximumFailoverAttempts: 5 + }, + Always: { + maximumFailoverAttempts: 5 + } + }, + logger: { + Log4j: { + level: { + clsName: 'org.apache.logging.log4j.Level' + } + }, + Log4j2: { + level: { + clsName: 'org.apache.logging.log4j.Level' + } + } + }, + marshalLocalJobs: false, + marshallerCacheKeepAliveTime: 10000, + metricsHistorySize: 10000, + metricsLogFrequency: 60000, + metricsUpdateFrequency: 2000, + clockSyncSamples: 8, + clockSyncFrequency: 120000, + timeServerPortBase: 31100, + timeServerPortRange: 100, + transactionConfiguration: { + defaultTxConcurrency: { + clsName: 'org.apache.ignite.transactions.TransactionConcurrency', + value: 'PESSIMISTIC' + }, + defaultTxIsolation: { + clsName: 'org.apache.ignite.transactions.TransactionIsolation', + value: 'REPEATABLE_READ' + }, + defaultTxTimeout: 0, + pessimisticTxLogLinger: 10000 + }, + attributes: { + keyClsName: 'java.lang.String', + valClsName: 'java.lang.String', + items: [] + }, + odbcConfiguration: { + endpointAddress: '0.0.0.0:10800..10810', + maxOpenCursors: 128 + }, + eventStorage: { + Memory: { + expireCount: 10000 + } + }, + checkpointSpi: { + S3: { + bucketNameSuffix: 'default-bucket', + clientConfiguration: { + protocol: { + clsName: 'com.amazonaws.Protocol', + value: 'HTTPS' + }, + maxConnections: 50, + retryPolicy: { + retryCondition: { + clsName: 'com.amazonaws.retry.PredefinedRetryPolicies' + }, + backoffStrategy: { + clsName: 'com.amazonaws.retry.PredefinedRetryPolicies' + }, + maxErrorRetry: { + clsName: 'com.amazonaws.retry.PredefinedRetryPolicies' + } + }, + maxErrorRetry: -1, + socketTimeout: 50000, + connectionTimeout: 50000, + requestTimeout: 0, + socketSendBufferSizeHints: 0, + connectionTTL: -1, + connectionMaxIdleMillis: 60000, + responseMetadataCacheSize: 50, + useReaper: true, + useGzip: false, + preemptiveBasicProxyAuth: false, + useTcpKeepAlive: false + } + }, + JDBC: { + checkpointTableName: 'CHECKPOINTS', + keyFieldName: 'NAME', + keyFieldType: 'VARCHAR', + valueFieldName: 'VALUE', + valueFieldType: 'BLOB', + expireDateFieldName: 'EXPIRE_DATE', + expireDateFieldType: 'DATETIME', + numberOfRetries: 2 + } + }, + loadBalancingSpi: { + RoundRobin: { + perTask: false + }, + Adaptive: { + loadProbe: { + Job: { + useAverage: true + }, + CPU: { + useAverage: true, + useProcessors: true, + processorCoefficient: 1 + }, + ProcessingTime: { + useAverage: true + } + } + }, + WeightedRandom: { + nodeWeight: 10, + useWeights: false + } + } +}; + +export default function() { + this.append = (dflts) => { + _.merge(DFLT_CLUSTER, dflts); + }; + + this.$get = [() => { + return DFLT_CLUSTER; + }]; +} http://git-wip-us.apache.org/repos/asf/ignite/blob/087f6405/modules/web-console/frontend/app/modules/configuration/generator/defaults/igfs.provider.js ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/modules/configuration/generator/defaults/igfs.provider.js b/modules/web-console/frontend/app/modules/configuration/generator/defaults/igfs.provider.js new file mode 100644 index 0000000..c556336 --- /dev/null +++ b/modules/web-console/frontend/app/modules/configuration/generator/defaults/igfs.provider.js @@ -0,0 +1,68 @@ +/* + * 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. + */ + +const DFLT_IGFS = { + defaultMode: { + clsName: 'org.apache.ignite.igfs.IgfsMode', + value: 'DUAL_ASYNC' + }, + secondaryFileSystem: { + + }, + ipcEndpointConfiguration: { + type: { + clsName: 'org.apache.ignite.igfs.IgfsIpcEndpointType' + }, + host: '127.0.0.1', + port: 10500, + memorySize: 262144, + tokenDirectoryPath: 'ipc/shmem' + }, + fragmentizerConcurrentFiles: 0, + fragmentizerThrottlingBlockLength: 16777216, + fragmentizerThrottlingDelay: 200, + dualModeMaxPendingPutsSize: 0, + dualModePutExecutorServiceShutdown: false, + blockSize: 65536, + streamBufferSize: 65536, + maxSpaceSize: 0, + maximumTaskRangeLength: 0, + managementPort: 11400, + perNodeBatchSize: 100, + perNodeParallelBatchCount: 8, + prefetchBlocks: 0, + sequentialReadsBeforePrefetch: 0, + trashPurgeTimeout: 1000, + colocateMetadata: true, + relaxedConsistency: true, + pathModes: { + keyClsName: 'java.lang.String', + keyField: 'path', + valClsName: 'org.apache.ignite.igfs.IgfsMode', + valField: 'mode' + } +}; + +export default function() { + this.append = (dflts) => { + _.merge(DFLT_IGFS, dflts); + }; + + this.$get = [() => { + return DFLT_IGFS; + }]; +} http://git-wip-us.apache.org/repos/asf/ignite/blob/087f6405/modules/web-console/frontend/app/modules/configuration/generator/generator-common.js ---------------------------------------------------------------------- diff --git a/modules/web-console/frontend/app/modules/configuration/generator/generator-common.js b/modules/web-console/frontend/app/modules/configuration/generator/generator-common.js new file mode 100644 index 0000000..d502c8a --- /dev/null +++ b/modules/web-console/frontend/app/modules/configuration/generator/generator-common.js @@ -0,0 +1,625 @@ +/* + * 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. + */ + +// Entry point for common functions for code generation. +const $generatorCommon = {}; + +// Add leading zero. +$generatorCommon.addLeadingZero = function(numberStr, minSize) { + if (typeof (numberStr) !== 'string') + numberStr = String(numberStr); + + while (numberStr.length < minSize) + numberStr = '0' + numberStr; + + return numberStr; +}; + +// Format date to string. +$generatorCommon.formatDate = function(date) { + const dd = $generatorCommon.addLeadingZero(date.getDate(), 2); + const mm = $generatorCommon.addLeadingZero(date.getMonth() + 1, 2); + + const yyyy = date.getFullYear(); + + return mm + '/' + dd + '/' + yyyy + ' ' + $generatorCommon.addLeadingZero(date.getHours(), 2) + ':' + $generatorCommon.addLeadingZero(date.getMinutes(), 2); +}; + +/** + * Generate title comment for XML, Java, ... files. + * + * @param sbj {string} What is generated. + * @returns {string} Text to add as title comment in generated java class. + */ +$generatorCommon.mainComment = function mainComment(sbj) { + return 'This ' + sbj + ' was generated by Ignite Web Console (' + $generatorCommon.formatDate(new Date()) + ')'; +}; + +// Create result holder with service functions and properties for XML and java code generation. +$generatorCommon.builder = function(deep) { + if (_.isNil($generatorCommon.JavaTypes)) + $generatorCommon.JavaTypes = angular.element(document.getElementById('app')).injector().get('JavaTypes'); + + const res = []; + + res.deep = deep || 0; + res.needEmptyLine = false; + res.lineStart = true; + res.datasources = []; + res.imports = {}; + res.staticImports = {}; + res.vars = {}; + + res.safeDeep = 0; + res.safeNeedEmptyLine = false; + res.safeImports = {}; + res.safeDatasources = []; + res.safePoint = -1; + + res.mergeProps = function(fromRes) { + if ($generatorCommon.isDefinedAndNotEmpty(fromRes)) { + res.datasources = fromRes.datasources; + + angular.extend(res.imports, fromRes.imports); + angular.extend(res.staticImports, fromRes.staticImports); + angular.extend(res.vars, fromRes.vars); + } + }; + + res.mergeLines = function(fromRes) { + if ($generatorCommon.isDefinedAndNotEmpty(fromRes)) { + if (res.needEmptyLine) + res.push(''); + + _.forEach(fromRes, function(line) { + res.append(line); + }); + } + }; + + res.startSafeBlock = function() { + res.safeDeep = this.deep; + this.safeNeedEmptyLine = this.needEmptyLine; + this.safeImports = _.cloneDeep(this.imports); + this.safeStaticImports = _.cloneDeep(this.staticImports); + this.safeDatasources = this.datasources.slice(); + this.safePoint = this.length; + }; + + res.rollbackSafeBlock = function() { + if (this.safePoint >= 0) { + this.splice(this.safePoint, this.length - this.safePoint); + + this.deep = res.safeDeep; + this.needEmptyLine = this.safeNeedEmptyLine; + this.datasources = this.safeDatasources; + this.imports = this.safeImports; + this.staticImports = this.safeStaticImports; + this.safePoint = -1; + } + }; + + res.asString = function() { + return this.join('\n'); + }; + + res.append = function(s) { + this.push((this.lineStart ? _.repeat(' ', this.deep) : '') + s); + + return this; + }; + + res.line = function(s) { + if (s) { + if (res.needEmptyLine) + res.push(''); + + res.append(s); + } + + res.needEmptyLine = false; + + res.lineStart = true; + + return res; + }; + + res.startBlock = function(s) { + if (s) { + if (this.needEmptyLine) + this.push(''); + + this.append(s); + } + + this.needEmptyLine = false; + + this.lineStart = true; + + this.deep++; + + return this; + }; + + res.endBlock = function(s) { + this.deep--; + + if (s) + this.append(s); + + this.lineStart = true; + + return this; + }; + + res.softEmptyLine = function() { + this.needEmptyLine = this.length > 0; + }; + + res.emptyLineIfNeeded = function() { + if (this.needEmptyLine) { + this.push(''); + this.lineStart = true; + + this.needEmptyLine = false; + } + }; + + /** + * Add class to imports. + * + * @param clsName Full class name. + * @returns {String} Short class name or full class name in case of names conflict. + */ + res.importClass = function(clsName) { + if ($generatorCommon.JavaTypes.isJavaPrimitive(clsName)) + return clsName; + + const fullClassName = $generatorCommon.JavaTypes.fullClassName(clsName); + + const dotIdx = fullClassName.lastIndexOf('.'); + + const shortName = dotIdx > 0 ? fullClassName.substr(dotIdx + 1) : fullClassName; + + if (this.imports[shortName]) { + if (this.imports[shortName] !== fullClassName) + return fullClassName; // Short class names conflict. Return full name. + } + else + this.imports[shortName] = fullClassName; + + return shortName; + }; + + /** + * Add class to imports. + * + * @param member Static member. + * @returns {String} Short class name or full class name in case of names conflict. + */ + res.importStatic = function(member) { + const dotIdx = member.lastIndexOf('.'); + + const shortName = dotIdx > 0 ? member.substr(dotIdx + 1) : member; + + if (this.staticImports[shortName]) { + if (this.staticImports[shortName] !== member) + return member; // Short class names conflict. Return full name. + } + else + this.staticImports[shortName] = member; + + return shortName; + }; + + /** + * @returns String with "java imports" section. + */ + res.generateImports = function() { + const genImports = []; + + for (const clsName in this.imports) { + if (this.imports.hasOwnProperty(clsName) && this.imports[clsName].lastIndexOf('java.lang.', 0) !== 0) + genImports.push('import ' + this.imports[clsName] + ';'); + } + + genImports.sort(); + + return genImports.join('\n'); + }; + + /** + * @returns String with "java imports" section. + */ + res.generateStaticImports = function() { + const statImports = []; + + for (const clsName in this.staticImports) { + if (this.staticImports.hasOwnProperty(clsName) && this.staticImports[clsName].lastIndexOf('java.lang.', 0) !== 0) + statImports.push('import static ' + this.staticImports[clsName] + ';'); + } + + statImports.sort(); + + return statImports.join('\n'); + }; + + return res; +}; + +// Eviction policies code generation descriptors. +$generatorCommon.EVICTION_POLICIES = { + LRU: { + className: 'org.apache.ignite.cache.eviction.lru.LruEvictionPolicy', + fields: {batchSize: {dflt: 1}, maxMemorySize: null, maxSize: {dflt: 100000}} + }, + FIFO: { + className: 'org.apache.ignite.cache.eviction.fifo.FifoEvictionPolicy', + fields: {batchSize: {dflt: 1}, maxMemorySize: null, maxSize: {dflt: 100000}} + }, + SORTED: { + className: 'org.apache.ignite.cache.eviction.sorted.SortedEvictionPolicy', + fields: {batchSize: {dflt: 1}, maxMemorySize: null, maxSize: {dflt: 100000}} + } +}; + +// Marshaller code generation descriptors. +$generatorCommon.MARSHALLERS = { + OptimizedMarshaller: { + className: 'org.apache.ignite.marshaller.optimized.OptimizedMarshaller', + fields: {poolSize: null, requireSerializable: null } + }, + JdkMarshaller: { + className: 'org.apache.ignite.marshaller.jdk.JdkMarshaller', + fields: {} + } +}; + +// Pairs of supported databases and their JDBC dialects. +$generatorCommon.JDBC_DIALECTS = { + Generic: 'org.apache.ignite.cache.store.jdbc.dialect.BasicJdbcDialect', + Oracle: 'org.apache.ignite.cache.store.jdbc.dialect.OracleDialect', + DB2: 'org.apache.ignite.cache.store.jdbc.dialect.DB2Dialect', + SQLServer: 'org.apache.ignite.cache.store.jdbc.dialect.SQLServerDialect', + MySQL: 'org.apache.ignite.cache.store.jdbc.dialect.MySQLDialect', + PostgreSQL: 'org.apache.ignite.cache.store.jdbc.dialect.BasicJdbcDialect', + H2: 'org.apache.ignite.cache.store.jdbc.dialect.H2Dialect' +}; + +// Return JDBC dialect full class name for specified database. +$generatorCommon.jdbcDialectClassName = function(db) { + const dialectClsName = $generatorCommon.JDBC_DIALECTS[db]; + + return dialectClsName ? dialectClsName : 'Unknown database: ' + db; +}; + +// Generate default data cache for specified igfs instance. +$generatorCommon.igfsDataCache = function(igfs) { + return { + name: igfs.name + '-data', + cacheMode: 'PARTITIONED', + atomicityMode: 'TRANSACTIONAL', + writeSynchronizationMode: 'FULL_SYNC', + backups: 0, + igfsAffinnityGroupSize: igfs.affinnityGroupSize || 512 + }; +}; + +// Generate default meta cache for specified igfs instance. +$generatorCommon.igfsMetaCache = function(igfs) { + return { + name: igfs.name + '-meta', + cacheMode: 'REPLICATED', + atomicityMode: 'TRANSACTIONAL', + writeSynchronizationMode: 'FULL_SYNC' + }; +}; + +// Pairs of supported databases and their data sources. +$generatorCommon.DATA_SOURCES = { + Generic: 'com.mchange.v2.c3p0.ComboPooledDataSource', + Oracle: 'oracle.jdbc.pool.OracleDataSource', + DB2: 'com.ibm.db2.jcc.DB2DataSource', + SQLServer: 'com.microsoft.sqlserver.jdbc.SQLServerDataSource', + MySQL: 'com.mysql.jdbc.jdbc2.optional.MysqlDataSource', + PostgreSQL: 'org.postgresql.ds.PGPoolingDataSource', + H2: 'org.h2.jdbcx.JdbcDataSource' +}; + +// Return data source full class name for specified database. +$generatorCommon.dataSourceClassName = function(db) { + const dsClsName = $generatorCommon.DATA_SOURCES[db]; + + return dsClsName ? dsClsName : 'Unknown database: ' + db; +}; + +// Store factories code generation descriptors. +$generatorCommon.STORE_FACTORIES = { + CacheJdbcPojoStoreFactory: { + className: 'org.apache.ignite.cache.store.jdbc.CacheJdbcPojoStoreFactory', + suffix: 'JdbcPojo', + fields: { + configuration: {type: 'bean'} + } + }, + CacheJdbcBlobStoreFactory: { + className: 'org.apache.ignite.cache.store.jdbc.CacheJdbcBlobStoreFactory', + suffix: 'JdbcBlob', + fields: { + initSchema: null, + createTableQuery: null, + loadQuery: null, + insertQuery: null, + updateQuery: null, + deleteQuery: null + } + }, + CacheHibernateBlobStoreFactory: { + className: 'org.apache.ignite.cache.store.hibernate.CacheHibernateBlobStoreFactory', + suffix: 'Hibernate', + fields: {hibernateProperties: {type: 'propertiesAsList', propVarName: 'props'}} + } +}; + +// Swap space SPI code generation descriptor. +$generatorCommon.SWAP_SPACE_SPI = { + className: 'org.apache.ignite.spi.swapspace.file.FileSwapSpaceSpi', + fields: { + baseDirectory: {type: 'path'}, + readStripesNumber: null, + maximumSparsity: {type: 'float'}, + maxWriteQueueSize: null, + writeBufferSize: null + } +}; + +// Transaction configuration code generation descriptor. +$generatorCommon.TRANSACTION_CONFIGURATION = { + className: 'org.apache.ignite.configuration.TransactionConfiguration', + fields: { + defaultTxConcurrency: {type: 'enum', enumClass: 'org.apache.ignite.transactions.TransactionConcurrency', dflt: 'PESSIMISTIC'}, + defaultTxIsolation: {type: 'enum', enumClass: 'org.apache.ignite.transactions.TransactionIsolation', dflt: 'REPEATABLE_READ'}, + defaultTxTimeout: {dflt: 0}, + pessimisticTxLogLinger: {dflt: 10000}, + pessimisticTxLogSize: null, + txSerializableEnabled: null, + txManagerFactory: {type: 'bean'} + } +}; + +// SSL configuration code generation descriptor. +$generatorCommon.SSL_CONFIGURATION_TRUST_FILE_FACTORY = { + className: 'org.apache.ignite.ssl.SslContextFactory', + fields: { + keyAlgorithm: null, + keyStoreFilePath: {type: 'path'}, + keyStorePassword: {type: 'raw'}, + keyStoreType: null, + protocol: null, + trustStoreFilePath: {type: 'path'}, + trustStorePassword: {type: 'raw'}, + trustStoreType: null + } +}; + +// SSL configuration code generation descriptor. +$generatorCommon.SSL_CONFIGURATION_TRUST_MANAGER_FACTORY = { + className: 'org.apache.ignite.ssl.SslContextFactory', + fields: { + keyAlgorithm: null, + keyStoreFilePath: {type: 'path'}, + keyStorePassword: {type: 'raw'}, + keyStoreType: null, + protocol: null, + trustManagers: {type: 'array'} + } +}; + +// Communication configuration code generation descriptor. +$generatorCommon.CONNECTOR_CONFIGURATION = { + className: 'org.apache.ignite.configuration.ConnectorConfiguration', + fields: { + jettyPath: null, + host: null, + port: {dflt: 11211}, + portRange: {dflt: 100}, + idleTimeout: {dflt: 7000}, + idleQueryCursorTimeout: {dflt: 600000}, + idleQueryCursorCheckFrequency: {dflt: 60000}, + receiveBufferSize: {dflt: 32768}, + sendBufferSize: {dflt: 32768}, + sendQueueLimit: {dflt: 0}, + directBuffer: {dflt: false}, + noDelay: {dflt: true}, + selectorCount: null, + threadPoolSize: null, + messageInterceptor: {type: 'bean'}, + secretKey: null, + sslEnabled: {dflt: false} + } +}; + +// Communication configuration code generation descriptor. +$generatorCommon.COMMUNICATION_CONFIGURATION = { + className: 'org.apache.ignite.spi.communication.tcp.TcpCommunicationSpi', + fields: { + listener: {type: 'bean'}, + localAddress: null, + localPort: {dflt: 47100}, + localPortRange: {dflt: 100}, + sharedMemoryPort: {dflt: 48100}, + directBuffer: {dflt: false}, + directSendBuffer: {dflt: false}, + idleConnectionTimeout: {dflt: 30000}, + connectTimeout: {dflt: 5000}, + maxConnectTimeout: {dflt: 600000}, + reconnectCount: {dflt: 10}, + socketSendBuffer: {dflt: 32768}, + socketReceiveBuffer: {dflt: 32768}, + messageQueueLimit: {dflt: 1024}, + slowClientQueueLimit: null, + tcpNoDelay: {dflt: true}, + ackSendThreshold: {dflt: 16}, + unacknowledgedMessagesBufferSize: {dflt: 0}, + socketWriteTimeout: {dflt: 2000}, + selectorsCount: null, + addressResolver: {type: 'bean'} + } +}; + +// Communication configuration code generation descriptor. +$generatorCommon.IGFS_IPC_CONFIGURATION = { + className: 'org.apache.ignite.igfs.IgfsIpcEndpointConfiguration', + fields: { + type: {type: 'enum', enumClass: 'org.apache.ignite.igfs.IgfsIpcEndpointType'}, + host: {dflt: '127.0.0.1'}, + port: {dflt: 10500}, + memorySize: {dflt: 262144}, + tokenDirectoryPath: {dflt: 'ipc/shmem'}, + threadCount: null + } +}; + +$generatorCommon.ODBC_CONFIGURATION = { + className: 'org.apache.ignite.configuration.OdbcConfiguration', + fields: { + endpointAddress: {dflt: '0.0.0.0:10800..10810'}, + maxOpenCursors: {dflt: 128} + } +}; + +// Check that cache has datasource. +$generatorCommon.cacheHasDatasource = function(cache) { + if (cache.cacheStoreFactory && cache.cacheStoreFactory.kind) { + const storeFactory = cache.cacheStoreFactory[cache.cacheStoreFactory.kind]; + + return !!(storeFactory && (storeFactory.connectVia ? (storeFactory.connectVia === 'DataSource' ? storeFactory.dialect : false) : storeFactory.dialect)); // eslint-disable-line no-nested-ternary + } + + return false; +}; + +$generatorCommon.secretPropertiesNeeded = function(cluster) { + return !_.isNil(_.find(cluster.caches, $generatorCommon.cacheHasDatasource)) || cluster.sslEnabled; +}; + +// Check that binary is configured. +$generatorCommon.binaryIsDefined = function(binary) { + return binary && ($generatorCommon.isDefinedAndNotEmpty(binary.idMapper) || $generatorCommon.isDefinedAndNotEmpty(binary.nameMapper) || + $generatorCommon.isDefinedAndNotEmpty(binary.serializer) || $generatorCommon.isDefinedAndNotEmpty(binary.typeConfigurations) || + (!_.isNil(binary.compactFooter) && !binary.compactFooter)); +}; + +// Extract domain model metadata location. +$generatorCommon.domainQueryMetadata = function(domain) { + return domain.queryMetadata ? domain.queryMetadata : 'Configuration'; +}; + +/** + * @param {Object} obj Object to check. + * @param {Array<String>} props Array of properties names. + * @returns {boolean} 'true' if + */ +$generatorCommon.hasAtLeastOneProperty = function(obj, props) { + return obj && props && _.findIndex(props, (prop) => !_.isNil(obj[prop])) >= 0; +}; + +/** + * Convert some name to valid java name. + * + * @param prefix To append to java name. + * @param name to convert. + * @returns {string} Valid java name. + */ +$generatorCommon.toJavaName = function(prefix, name) { + const javaName = name ? name.replace(/[^A-Za-z_0-9]+/g, '_') : 'dflt'; + + return prefix + javaName.charAt(0).toLocaleUpperCase() + javaName.slice(1); +}; + +/** + * @param v Value to check. + * @returns {boolean} 'true' if value defined and not empty string. + */ +$generatorCommon.isDefinedAndNotEmpty = function(v) { + let defined = !_.isNil(v); + + if (defined && (_.isString(v) || _.isArray(v))) + defined = v.length > 0; + + return defined; +}; + +/** + * @param {Object} obj Object to check. + * @param {Array<String>} props Properties names. + * @returns {boolean} 'true' if object contains at least one from specified properties. + */ +$generatorCommon.hasProperty = function(obj, props) { + for (const propName in props) { + if (props.hasOwnProperty(propName)) { + if (obj[propName]) + return true; + } + } + + return false; +}; + +/** + * Get class for selected implementation of Failover SPI. + * + * @param spi Failover SPI configuration. + * @returns {*} Class for selected implementation of Failover SPI. + */ +$generatorCommon.failoverSpiClass = function(spi) { + switch (spi.kind) { + case 'JobStealing': return 'org.apache.ignite.spi.failover.jobstealing.JobStealingFailoverSpi'; + case 'Never': return 'org.apache.ignite.spi.failover.never.NeverFailoverSpi'; + case 'Always': return 'org.apache.ignite.spi.failover.always.AlwaysFailoverSpi'; + case 'Custom': return _.get(spi, 'Custom.class'); + default: return 'Unknown'; + } +}; + +$generatorCommon.loggerConfigured = function(logger) { + if (logger && logger.kind) { + const log = logger[logger.kind]; + + switch (logger.kind) { + case 'Log4j2': return log && $generatorCommon.isDefinedAndNotEmpty(log.path); + + case 'Log4j': + if (!log || !log.mode) + return false; + + if (log.mode === 'Path') + return $generatorCommon.isDefinedAndNotEmpty(log.path); + + return true; + + case 'Custom': return log && $generatorCommon.isDefinedAndNotEmpty(log.class); + + default: + return true; + } + } + + return false; +}; + +export default $generatorCommon;
