Return-Path: X-Original-To: apmail-ignite-commits-archive@minotaur.apache.org Delivered-To: apmail-ignite-commits-archive@minotaur.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 8F8FD18655 for ; Tue, 25 Aug 2015 07:26:12 +0000 (UTC) Received: (qmail 5940 invoked by uid 500); 25 Aug 2015 07:26:12 -0000 Delivered-To: apmail-ignite-commits-archive@ignite.apache.org Received: (qmail 5900 invoked by uid 500); 25 Aug 2015 07:26:12 -0000 Mailing-List: contact commits-help@ignite.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@ignite.apache.org Delivered-To: mailing list commits@ignite.apache.org Received: (qmail 5889 invoked by uid 99); 25 Aug 2015 07:26:12 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 25 Aug 2015 07:26:12 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 24877DFCF2; Tue, 25 Aug 2015 07:26:12 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: akuznetsov@apache.org To: commits@ignite.apache.org Date: Tue, 25 Aug 2015 07:26:13 -0000 Message-Id: <5ce611852c5e4b5e96cfa1aa43a6359d@git.apache.org> In-Reply-To: <842ff465afef43ddae7537f55dcd9694@git.apache.org> References: <842ff465afef43ddae7537f55dcd9694@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [2/3] ignite git commit: IGNITE-843 WIP on preview. http://git-wip-us.apache.org/repos/asf/ignite/blob/0b72d82a/modules/control-center-web/src/main/js/routes/generator/generator-java.js ---------------------------------------------------------------------- diff --git a/modules/control-center-web/src/main/js/routes/generator/generator-java.js b/modules/control-center-web/src/main/js/routes/generator/generator-java.js new file mode 100644 index 0000000..9065a2b --- /dev/null +++ b/modules/control-center-web/src/main/js/routes/generator/generator-java.js @@ -0,0 +1,886 @@ +/* + * 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. + */ + +if (typeof window === 'undefined') { + _ = require('lodash'); + + $commonUtils = require('../../helpers/common-utils'); + $dataStructures = require('../../helpers/data-structures'); + $generatorCommon = require('./generator-common'); +} + + +/** + * Convert some name to valid java name. + * + * @param prefix To append to java name. + * @param name to convert. + * @returns {string} Valid java name. + */ +function toJavaName(prefix, name) { + var javaName = name.replace(/[^A-Za-z_0-9]+/, '_'); + + return prefix + javaName.charAt(0).toLocaleUpperCase() + javaName.slice(1); +} + +/** + * Add eviction policy. + * + * @param res Resulting output with generated code. + * @param varName Current using variable name. + * @param evictionPolicy Data to add. + * @param propertyName Name in source data. + */ +function addEvictionPolicy(res, varName, evictionPolicy, propertyName) { + if (evictionPolicy && evictionPolicy.kind) { + var e = $generatorCommon.EVICTION_POLICIES[evictionPolicy.kind]; + + var obj = evictionPolicy[evictionPolicy.kind.toUpperCase()]; + + addBeanWithProperties(res, varName, obj, propertyName, propertyName, e.className, e.fields, true); + } +} + +function addCacheTypeMetadataDatabaseFields(res, meta, fieldProperty) { + var dbFields = meta[fieldProperty]; + + if (dbFields && dbFields.length > 0) { + res.line(); + + declareVariable(res, needNewVariable(res, fieldProperty), fieldProperty, 'java.util.Collection', 'java.util.ArrayList', 'org.apache.ignite.cache.CacheTypeFieldMetadata'); + + _.forEach(dbFields, function (field) { + res.line(fieldProperty + '.add(new CacheTypeFieldMetadata(' + + '"' + field.databaseName + '", ' + + 'java.sql.Types.' + field.databaseType + ', ' + + '"' + field.javaName + '", ' + + field.javaType + '.class' + + '));'); + }); + + res.line('typeMeta.' + toJavaName('set', fieldProperty) + '(' + fieldProperty + ');'); + } +} + +function addCacheTypeMetadataQueryFields(res, meta, fieldProperty) { + var fields = meta[fieldProperty]; + + if (fields && fields.length > 0) { + res.line(); + + declareVariable(res, needNewVariable(res, fieldProperty), fieldProperty, 'java.util.Map', 'java.util.LinkedHashMap', 'java.lang.String', 'java.lang.Class'); + + _.forEach(fields, function (field) { + res.line(fieldProperty + '.put("' + field.name + '", ' + res.importClass(field.className) + '.class);'); + }); + + res.line('typeMeta.' + toJavaName('set', fieldProperty) + '(' + fieldProperty + ');'); + } +} + +function addCacheTypeMetadataGroups(res, meta) { + var groups = meta.groups; + + if (groups && groups.length > 0) { + _.forEach(groups, function (group) { + var fields = group.fields; + + if (fields && fields.length > 0) { + res.importClass('java.util.Map'); + res.importClass('java.util.LinkedHashMap'); + res.importClass('org.apache.ignite.lang.IgniteBiTuple'); + + var varNew = !res.groups; + + res.line(); + res.line((varNew ? 'Map, Boolean>>> ' : '') + + "groups = new LinkedHashMap<>();"); + + if (varNew) + res.groups = true; + + varNew = !res.groupItems; + + res.line((varNew ? 'LinkedHashMap, Boolean>> ' : '') + + 'groupItems = new LinkedHashMap<>();'); + + if (varNew) + res.groupItems = true; + + _.forEach(fields, function (field) { + res.line('groupItems.put("' + field.name + '", ' + + 'new IgniteBiTuple, Boolean>(' + res.importClass(field.className) + '.class, ' + field.direction + '));'); + }); + + res.line('groups.put("' + group.name + '", groupItems);'); + } + }); + + res.line('typeMeta.setGroups(groups);'); + } +} + +function addCacheTypeMetadataConfiguration(res, meta) { + declareVariable(res, needNewVariable(res, 'typeMeta'), 'typeMeta', 'org.apache.ignite.cache.CacheTypeMetadata'); + + var kind = meta.kind; + + var keyType = addClassProperty(res, 'typeMeta', meta, 'keyType'); + addClassProperty(res, 'typeMeta', meta, 'valueType'); + + if (kind != 'query') { + addProperty(res, 'typeMeta', meta, 'databaseSchema'); + addProperty(res, 'typeMeta', meta, 'databaseTable'); + + if (!$dataStructures.isJavaBuildInClass(keyType)) + addCacheTypeMetadataDatabaseFields(res, meta, 'keyFields'); + + addCacheTypeMetadataDatabaseFields(res, meta, 'valueFields'); + } + + if (kind != 'store') { + addCacheTypeMetadataQueryFields(res, meta, 'queryFields'); + addCacheTypeMetadataQueryFields(res, meta, 'ascendingFields'); + addCacheTypeMetadataQueryFields(res, meta, 'descendingFields'); + + res.needEmptyLine = true; + addListProperty(res, 'typeMeta', meta, 'textFields'); + + addCacheTypeMetadataGroups(res, meta); + } + + res.line(); + res.line('types.add(typeMeta);'); + res.line(); +} + +/** + * Generate java code for cache configuration. + * + * @param cache Cache config. + * @param varName Variable name. + * @param res Result builder. + * @returns {*} Append generated java code to builder and return it. + */ +function addCacheConfiguration(res, cache, varName) { + res.emptyLineIfNeeded(); + + res.importClass('org.apache.ignite.cache.CacheAtomicityMode'); + res.importClass('org.apache.ignite.cache.CacheMode'); + + declareVariable(res, true, varName, 'org.apache.ignite.configuration.CacheConfiguration'); + + res.needEmptyLine = true; + + addProperty(res, varName, cache, 'name'); + + var cacheMode = addProperty(res, varName, cache, 'mode', 'CacheMode', 'cacheMode'); + + addProperty(res, varName, cache, 'atomicityMode', 'CacheAtomicityMode'); + + if (cacheMode == 'PARTITIONED') + addProperty(res, varName, cache, 'backups'); + + addProperty(res, varName, cache, 'readFromBackup'); + addProperty(res, varName, cache, 'startSize'); + + res.needEmptyLine = true; + + addProperty(res, varName, cache, 'memoryMode', 'CacheMemoryMode'); + addProperty(res, varName, cache, 'offHeapMaxMemory'); + addProperty(res, varName, cache, 'swapEnabled'); + addProperty(res, varName, cache, 'copyOnRead'); + + res.needEmptyLine = true; + + addEvictionPolicy(res, varName, cache.evictionPolicy, 'evictionPolicy'); + + if (cacheMode == 'PARTITIONED' && cache.nearCacheEnabled) { + res.needEmptyLine = true; + + res.importClass('org.apache.ignite.configuration.NearCacheConfiguration'); + + addBeanWithProperties(res, varName, cache.nearConfiguration, 'nearConfiguration', 'nearConfiguration', + 'NearCacheConfiguration', {nearStartSize: null}, true); + + if (cache.nearConfiguration && cache.nearConfiguration.nearEvictionPolicy && cache.nearConfiguration.nearEvictionPolicy.kind) { + addEvictionPolicy(res, 'nearConfiguration', cache.nearConfiguration.nearEvictionPolicy, 'nearEvictionPolicy'); + } + } + + res.needEmptyLine = true; + + addProperty(res, varName, cache, 'sqlEscapeAll'); + addProperty(res, varName, cache, 'sqlOnheapRowCacheSize'); + addProperty(res, varName, cache, 'longQueryWarningTimeout'); + + if (cache.indexedTypes && cache.indexedTypes.length > 0) { + res.emptyLineIfNeeded(); + + res.append(varName + '.setIndexedTypes('); + + for (var i = 0; i < cache.indexedTypes.length; i++) { + if (i > 0) + res.append(', '); + + var pair = cache.indexedTypes[i]; + + res.append(toJavaCode(res.importClass(pair.keyClass), 'class')).append(', ').append(toJavaCode(res.importClass(pair.valueClass), 'class')) + } + + res.line(');'); + } + + addMultiparamProperty(res, varName, cache, 'sqlFunctionClasses', 'class'); + + res.needEmptyLine = true; + + if (cacheMode != 'LOCAL') { + addProperty(res, varName, cache, 'rebalanceMode', 'CacheRebalanceMode'); + addProperty(res, varName, cache, 'rebalanceThreadPoolSize'); + addProperty(res, varName, cache, 'rebalanceBatchSize'); + addProperty(res, varName, cache, 'rebalanceOrder'); + addProperty(res, varName, cache, 'rebalanceDelay'); + addProperty(res, varName, cache, 'rebalanceTimeout'); + addProperty(res, varName, cache, 'rebalanceThrottle'); + + res.needEmptyLine = true; + } + + if (cache.cacheStoreFactory && cache.cacheStoreFactory.kind) { + var storeFactory = cache.cacheStoreFactory[cache.cacheStoreFactory.kind]; + var data = $generatorCommon.STORE_FACTORIES[cache.cacheStoreFactory.kind]; + + var sfVarName = toJavaName('storeFactory', cache.name); + var dsVarName = 'none'; + + if (storeFactory.dialect) { + var dataSourceBean = storeFactory.dataSourceBean; + + dsVarName = toJavaName('dataSource', dataSourceBean); + + if (!_.contains(res.datasourceBeans, dataSourceBean)) { + res.datasourceBeans.push(dataSourceBean); + + var dataSource = $generatorCommon.DATA_SOURCES[storeFactory.dialect]; + + res.line(); + + declareVariable(res, true, dsVarName, dataSource); + + res.line(dsVarName + '.setURL(_URL_);'); + res.line(dsVarName + '.setUsername(_User_Name_);'); + res.line(dsVarName + '.setPassword(_Password_);'); + } + } + + addBeanWithProperties(res, varName, storeFactory, 'cacheStoreFactory', sfVarName, data.className, + data.fields, true); + + if (dsVarName != 'none') + res.line(sfVarName + '.setDataSource(' + dsVarName + ');'); + } + + res.needEmptyLine = true; + + addProperty(res, varName, cache, 'loadPreviousValue'); + addProperty(res, varName, cache, 'readThrough'); + addProperty(res, varName, cache, 'writeThrough'); + + res.needEmptyLine = true; + + addProperty(res, varName, cache, 'invalidate'); + addProperty(res, varName, cache, 'defaultLockTimeout'); + addProperty(res, varName, cache, 'transactionManagerLookupClassName'); + + res.needEmptyLine = true; + + addProperty(res, varName, cache, 'writeBehindEnabled'); + addProperty(res, varName, cache, 'writeBehindBatchSize'); + addProperty(res, varName, cache, 'writeBehindFlushSize'); + addProperty(res, varName, cache, 'writeBehindFlushFrequency'); + addProperty(res, varName, cache, 'writeBehindFlushThreadCount'); + + res.needEmptyLine = true; + + addProperty(res, varName, cache, 'statisticsEnabled'); + addProperty(res, varName, cache, 'managementEnabled'); + + res.needEmptyLine = true; + + addProperty(res, varName, cache, 'maxConcurrentAsyncOperations'); + + res.needEmptyLine = true; + + // Generate cache type metadata configs. + if ((cache.queryMetadata && cache.queryMetadata.length > 0) || + (cache.storeMetadata && cache.storeMetadata.length > 0)) { + res.emptyLineIfNeeded(); + + declareVariable(res, needNewVariable(res, 'types'), 'types', 'java.util.Collection', 'java.util.ArrayList', 'org.apache.ignite.cache.CacheTypeMetadata'); + res.line(); + + var metaNames = []; + + if (cache.queryMetadata && cache.queryMetadata.length > 0) { + _.forEach(cache.queryMetadata, function (meta) { + if (!_.contains(metaNames, meta.name)) { + metaNames.push(meta.name); + + addCacheTypeMetadataConfiguration(res, meta); + } + }); + } + + if (cache.storeMetadata && cache.storeMetadata.length > 0) { + _.forEach(cache.storeMetadata, function (meta) { + if (!_.contains(metaNames, meta.name)) { + metaNames.push(meta.name); + + addCacheTypeMetadataConfiguration(res, meta); + } + }); + } + + res.line(varName + '.setTypeMetadata(types);'); + } +} + +function toJavaCode(val, type) { + if (val == null) + return 'null'; + + if (type == 'float') + return val + 'f'; + + if (type == 'class') + return val + '.class'; + + if (type) + return type + '.' + val; + + if (typeof(val) == 'string') + return '"' + val.replace('"', '\\"') + '"'; + + if (typeof(val) == 'number' || typeof(val) == 'boolean') + return '' + val; + + throw "Unknown type: " + typeof(val) + ' (' + val + ')'; +} + +function needNewVariable(res, varName) { + var needNew = !res[varName]; + + if (needNew) + res[varName] = true; + + return needNew; +} + +/** + * Add variable declaration. + * + * @param res Resulting output with generated code. + * @param varNew If 'true' then declare new variable otherwise reuse previously declared variable. + * @param varName Variable name. + * @param varFullType Variable full class name to be added to imports. + * @param varFullActualType Variable actual full class name to be added to imports. + * @param varFullGenericType1 Optional full class name of first generic. + * @param varFullGenericType2 Optional full class name of second generic. + */ +function declareVariable(res, varNew, varName, varFullType, varFullActualType, varFullGenericType1, varFullGenericType2) { + var varType = res.importClass(varFullType); + + if (varFullActualType && varFullGenericType1) { + var varActualType = res.importClass(varFullActualType); + var varGenericType1 = res.importClass(varFullGenericType1); + + if (varFullGenericType2) + var varGenericType2 = res.importClass(varFullGenericType2); + + res.line((varNew ? (varType + '<' + varGenericType1 + (varGenericType2 ? ', ' + varGenericType2 : '') + '> ') : '') + varName + ' = new ' + varActualType + '<>();'); + } + else + res.line((varNew ? (varType + ' ') : '') + varName + ' = new ' + varType + '();'); +} + +/** + * Add property via setter / property name. + * + * @param res Resulting output with generated code. + * @param varName Variable name. + * @param obj Source object with data. + * @param propName Property name to take from source object. + * @param enumType Optional info about property datatype. + * @param setterName Optional special setter name. + */ +function addProperty(res, varName, obj, propName, enumType, setterName) { + var val = obj[propName]; + + if ($commonUtils.isDefined(val)) { + res.emptyLineIfNeeded(); + + res.line(varName + '.' + getSetterName(setterName ? setterName : propName) + + '(' + toJavaCode(val, enumType) + ');'); + } + + return val; +} + +/** + * Add property via setter assuming that it is a 'Class'. + * + * @param res Resulting output with generated code. + * @param varName Variable name. + * @param obj Source object with data. + * @param propName Property name to take from source object. + */ +function addClassProperty(res, varName, obj, propName) { + var val = obj[propName]; + + if ($commonUtils.isDefined(val)) { + res.emptyLineIfNeeded(); + + res.line(varName + '.' + getSetterName(propName) + '(' + res.importClass(val) + '.class);'); + } +} + +/** + * @param propName Property name + * @returns Property setter with name by java conventions. + */ +function getSetterName(propName) { + return toJavaName('set', propName); +} + +function addListProperty(res, varName, obj, propName, enumType, setterName) { + var val = obj[propName]; + + if (val && val.length > 0) { + res.emptyLineIfNeeded(); + + res.importClass('java.util.Arrays'); + + res.append(varName + '.' + getSetterName(setterName ? setterName : propName) + '(Arrays.asList('); + + for (var i = 0; i < val.length; i++) { + if (i > 0) + res.append(', '); + + res.append(toJavaCode(val[i], enumType)); + } + + res.line('));'); + } +} + +function addMultiparamProperty(res, varName, obj, propName, type, setterName) { + var val = obj[propName]; + + if (val && val.length > 0) { + res.append(varName + '.' + getSetterName(setterName ? setterName : propName) + '('); + + for (var i = 0; i < val.length; i++) { + if (i > 0) + res.append(', '); + + res.append(toJavaCode(val[i], type)); + } + + res.line(');'); + } +} + +function addBeanWithProperties(res, varName, bean, beanPropName, beanVarName, beanClass, props, createBeanAlthoughNoProps) { + if (bean && $commonUtils.hasProperty(bean, props)) { + if (!res.emptyLineIfNeeded()) { + res.line(); + } + + res.line(beanClass + ' ' + beanVarName + ' = new ' + beanClass + '();'); + + for (var propName in props) { + if (props.hasOwnProperty(propName)) { + var descr = props[propName]; + + if (descr) { + switch (descr.type) { + case 'list': + addListProperty(res, beanVarName, bean, propName, descr.elementsType, descr.setterName); + break; + + case 'enum': + addProperty(res, beanVarName, bean, propName, descr.enumClass, descr.setterName); + break; + + case 'float': + addProperty(res, beanVarName, bean, propName, 'float', descr.setterName); + break; + + case 'propertiesAsList': + var val = bean[propName]; + + if (val && val.length > 0) { + res.line('Properties ' + descr.propVarName + ' = new Properties();'); + + for (var i = 0; i < val.length; i++) { + var nameAndValue = val[i]; + + var eqIndex = nameAndValue.indexOf('='); + if (eqIndex >= 0) { + res.line(descr.propVarName + '.setProperty(' + + nameAndValue.substring(0, eqIndex) + ', ' + + nameAndValue.substr(eqIndex + 1) + ');'); + } + + } + + res.line(beanVarName + '.' + getSetterName(propName) + '(' + descr.propVarName + ');'); + } + break; + + case 'className': + if (bean[propName]) { + res.line(beanVarName + '.' + getSetterName(propName) + '(new ' + $generatorCommon.KNOWN_CLASSES[bean[propName]].className + '());'); + } + + break; + + default: + addProperty(res, beanVarName, bean, propName, null, descr.setterName); + } + } + else { + addProperty(res, beanVarName, bean, propName); + } + } + } + + res.line(varName + '.' + getSetterName(beanPropName) + '(' + beanVarName + ');'); + + res.needEmptyLine = true; + } + else if (createBeanAlthoughNoProps) { + res.emptyLineIfNeeded(); + + res.line(varName + '.' + getSetterName(beanPropName) + '(new ' + beanClass + '());'); + } +} + + +$generatorJava = {}; + +/** + * Function to generate java code for cluster configuration. + * + * @param cluster Cluster to process. + * @param javaClass If 'true' then generate factory class otherwise generate code snippet. + * @param clientNearConfiguration Near cache configuration for client node. + */ +$generatorJava.generateClusterConfiguration = function (cluster, javaClass, clientNearConfiguration) { + var res = $generatorCommon.builder(); + + res.datasourceBeans = []; + + if (javaClass) { + res.line('/**'); + res.line(' * ' + $generatorCommon.mainComment()); + res.line(' */'); + res.startBlock('public class ConfigurationFactory {'); + res.line('/**'); + res.line(' * Configure grid.'); + res.line(' */'); + res.startBlock('public IgniteConfiguration createConfiguration() {'); + } + + declareVariable(res, true, 'cfg', 'org.apache.ignite.configuration.IgniteConfiguration'); + res.line(); + + if (clientNearConfiguration) { + res.line('cfg.setClientMode(true);'); + res.line(); + } + + if (cluster.discovery) { + var d = cluster.discovery; + + declareVariable(res, true, 'discovery', 'org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi'); + + switch (d.kind) { + case 'Multicast': + res.importClass('org.apache.ignite.spi.discovery.tcp.ipfinder.multicast.TcpDiscoveryMulticastIpFinder'); + + addBeanWithProperties(res, 'discovery', d.Multicast, 'ipFinder', 'ipFinder', + 'TcpDiscoveryMulticastIpFinder', { + multicastGroup: null, + multicastPort: null, + responseWaitTime: null, + addressRequestAttempts: null, + localAddress: null + }, true); + + break; + + case 'Vm': + res.importClass('org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder'); + + addBeanWithProperties(res, 'discovery', d.Vm, 'ipFinder', 'ipFinder', 'TcpDiscoveryVmIpFinder', { + addresses: {type: 'list'} + }, true); + + break; + + case 'S3': + res.importClass('org.apache.ignite.spi.discovery.tcp.ipfinder.s3.TcpDiscoveryS3IpFinder'); + + if (d.S3) + addBeanWithProperties(res, 'discovery', d.S3, 'ipFinder', 'ipFinder', 'TcpDiscoveryS3IpFinder', + {bucketName: null}, true); + else + res.line('discovery.setIpFinder(new TcpDiscoveryS3IpFinder());'); + + break; + + case 'Cloud': + res.importClass('org.apache.ignite.spi.discovery.tcp.ipfinder.cloud.TcpDiscoveryCloudIpFinder'); + + addBeanWithProperties(res, 'discovery', d.Cloud, 'ipFinder', 'ipFinder', 'TcpDiscoveryCloudIpFinder', { + credential: null, + credentialPath: null, + identity: null, + provider: null, + regions: {type: 'list'}, + zones: {type: 'list'} + }, true); + + break; + + case 'GoogleStorage': + res.importClass('org.apache.ignite.spi.discovery.tcp.ipfinder.gce.TcpDiscoveryGoogleStorageIpFinder'); + + addBeanWithProperties(res, 'discovery', d.GoogleStorage, 'ipFinder', 'ipFinder', + 'TcpDiscoveryGoogleStorageIpFinder', { + projectName: null, + bucketName: null, + serviceAccountP12FilePath: null, + serviceAccountId: null + }, true); + + //if (d.GoogleStorage.addrReqAttempts) todo ???? + // res.line(''); + + break; + + case 'Jdbc': + res.line(); + + declareVariable(res, true, 'ipFinder', 'org.apache.ignite.spi.discovery.tcp.ipfinder.jdbc.TcpDiscoveryJdbcIpFinder'); + + res.line('ipFinder.setInitSchema(' + ($commonUtils.isDefined(d.Jdbc.initSchema) && d.Jdbc.initSchema) + ');'); + res.line('discovery.setIpFinder(ipFinder);'); + res.needEmptyLine = true; + + break; + + case 'SharedFs': + res.importClass('org.apache.ignite.spi.discovery.tcp.ipfinder.sharedfs.TcpDiscoverySharedFsIpFinder'); + + addBeanWithProperties(res, 'discovery', d.SharedFs, 'ipFinder', 'ipFinder', + 'TcpDiscoverySharedFsIpFinder', {path: null}, true); + + break; + + default: + throw 'Unknown discovery kind: ' + d.kind; + } + + res.emptyLineIfNeeded(); + + res.line('cfg.setDiscoverySpi(discovery);'); + + res.needEmptyLine = true; + } + + var caches = cluster.caches; + + if (caches && caches.length > 0) { + res.emptyLineIfNeeded(); + + var names = []; + + _.forEach(caches, function (cache) { + res.emptyLineIfNeeded(); + + var cacheName = toJavaName('cache', cache.name); + + names.push(cacheName); + + addCacheConfiguration(res, cache, cacheName); + + res.needEmptyLine = true; + }); + + res.emptyLineIfNeeded(); + + res.append('cfg.setCacheConfiguration('); + + for (var i = 0; i < names.length; i++) { + if (i > 0) + res.append(', '); + + res.append(names[i]); + } + + res.line(');'); + + res.needEmptyLine = true; + } + + var atomicCfg = $generatorCommon.ATOMIC_CONFIGURATION; + + addBeanWithProperties(res, 'cfg', cluster.atomicConfiguration, 'atomicConfiguration', 'atomicCfg', + atomicCfg.className, atomicCfg.fields); + + res.needEmptyLine = true; + + addProperty(res, 'cfg', cluster, 'networkTimeout'); + addProperty(res, 'cfg', cluster, 'networkSendRetryDelay'); + addProperty(res, 'cfg', cluster, 'networkSendRetryCount'); + addProperty(res, 'cfg', cluster, 'segmentCheckFrequency'); + addProperty(res, 'cfg', cluster, 'waitForSegmentOnStart'); + addProperty(res, 'cfg', cluster, 'discoveryStartupDelay'); + + res.needEmptyLine = true; + + addProperty(res, 'cfg', cluster, 'deploymentMode', 'DeploymentMode'); + + res.needEmptyLine = true; + + if (cluster.includeEventTypes && cluster.includeEventTypes.length > 0) { + res.emptyLineIfNeeded(); + + if (cluster.includeEventTypes.length == 1) { + res.importClass('org.apache.ignite.events.EventType'); + + res.line('cfg.setIncludeEventTypes(EventType.' + cluster.includeEventTypes[0] + ');'); + } + else { + res.append('int[] events = new int[EventType.' + cluster.includeEventTypes[0] + '.length'); + + for (i = 1; i < cluster.includeEventTypes.length; i++) { + res.line(); + + res.append(' + EventType.' + cluster.includeEventTypes[i] + '.length'); + } + + res.line('];'); + res.line(); + res.line('int k = 0;'); + + for (i = 0; i < cluster.includeEventTypes.length; i++) { + res.line(); + + var e = cluster.includeEventTypes[i]; + + res.line('System.arraycopy(EventType.' + e + ', 0, events, k, EventType.' + e + '.length);'); + res.line('k += EventType.' + e + '.length;'); + } + + res.line(); + res.line('cfg.setIncludeEventTypes(events);'); + } + + res.needEmptyLine = true; + } + + res.needEmptyLine = true; + + var marshaller = cluster.marshaller; + + if (marshaller && marshaller.kind) { + var marshallerDesc = $generatorCommon.MARSHALLERS[marshaller.kind]; + + addBeanWithProperties(res, 'cfg', marshaller[marshaller.kind], 'marshaller', 'marshaller', + marshallerDesc.className, marshallerDesc.fields, true); + + addBeanWithProperties(res, 'marshaller', marshaller[marshaller.kind], marshallerDesc.className, marshallerDesc.fields, true); + } + + addProperty(res, 'cfg', cluster, 'marshalLocalJobs'); + addProperty(res, 'cfg', cluster, 'marshallerCacheKeepAliveTime'); + addProperty(res, 'cfg', cluster, 'marshallerCacheThreadPoolSize'); + + res.needEmptyLine = true; + + addProperty(res, 'cfg', cluster, 'metricsExpireTime'); + addProperty(res, 'cfg', cluster, 'metricsHistorySize'); + addProperty(res, 'cfg', cluster, 'metricsLogFrequency'); + addProperty(res, 'cfg', cluster, 'metricsUpdateFrequency'); + res.needEmptyLine = true; + + addProperty(res, 'cfg', cluster, 'peerClassLoadingEnabled'); + addMultiparamProperty(res, 'cfg', cluster, 'peerClassLoadingLocalClassPathExclude'); + addProperty(res, 'cfg', cluster, 'peerClassLoadingMissedResourcesCacheSize'); + addProperty(res, 'cfg', cluster, 'peerClassLoadingThreadPoolSize'); + res.needEmptyLine = true; + + if (cluster.swapSpaceSpi && cluster.swapSpaceSpi.kind == 'FileSwapSpaceSpi') { + addBeanWithProperties(res, 'cfg', cluster.swapSpaceSpi.FileSwapSpaceSpi, 'swapSpaceSpi', 'swapSpi', + $generatorCommon.SWAP_SPACE_SPI.className, $generatorCommon.SWAP_SPACE_SPI.fields, true); + + res.needEmptyLine = true; + } + + addProperty(res, 'cfg', cluster, 'clockSyncSamples'); + addProperty(res, 'cfg', cluster, 'clockSyncFrequency'); + addProperty(res, 'cfg', cluster, 'timeServerPortBase'); + addProperty(res, 'cfg', cluster, 'timeServerPortRange'); + + res.needEmptyLine = true; + + addProperty(res, 'cfg', cluster, 'publicThreadPoolSize'); + addProperty(res, 'cfg', cluster, 'systemThreadPoolSize'); + addProperty(res, 'cfg', cluster, 'managementThreadPoolSize'); + addProperty(res, 'cfg', cluster, 'igfsThreadPoolSize'); + + res.needEmptyLine = true; + + addBeanWithProperties(res, 'cfg', cluster.transactionConfiguration, 'transactionConfiguration', + 'transactionConfiguration', $generatorCommon.TRANSACTION_CONFIGURATION.className, + $generatorCommon.TRANSACTION_CONFIGURATION.fields); + + res.needEmptyLine = true; + + addProperty(res, 'cfg', cluster, 'cacheSanityCheckEnabled'); + + res.needEmptyLine = true; + + if (javaClass) { + res.line(); + res.line('return cfg;'); + res.endBlock('}'); + res.endBlock('}'); + + return res.generateImports() + '\n\n' + res.join('') + } + + return res.join(''); +}; + +if (typeof window === 'undefined') { + module.exports = $generatorJava; +} http://git-wip-us.apache.org/repos/asf/ignite/blob/0b72d82a/modules/control-center-web/src/main/js/routes/generator/generator-properties.js ---------------------------------------------------------------------- diff --git a/modules/control-center-web/src/main/js/routes/generator/generator-properties.js b/modules/control-center-web/src/main/js/routes/generator/generator-properties.js new file mode 100644 index 0000000..d26d971 --- /dev/null +++ b/modules/control-center-web/src/main/js/routes/generator/generator-properties.js @@ -0,0 +1,269 @@ +/* + * 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. + */ + +if (typeof window === 'undefined') { + $dataStructures = require('../../helpers/data-structures'); +} + +function _addLeadingZero(numberStr, minSize) { + if (typeof (numberStr) != 'string') + numberStr = '' + numberStr; + + while (numberStr.length < minSize) { + numberStr = '0' + numberStr; + } + + return numberStr; +} + +function _formatDate(date) { + var dd = _addLeadingZero(date.getDate(), 2); + var mm = _addLeadingZero(date.getMonth() + 1, 2); + + var yyyy = date.getFullYear(); + + return mm + '/' + dd + '/' + yyyy + ' ' + _addLeadingZero(date.getHours(), 2) + ':' + _addLeadingZero(date.getMinutes(), 2); +} + +$generatorCommon = {}; + +$generatorCommon.isDefined = function (v) { + return !(v === undefined || v === null); +}; + +$generatorCommon.hasProperty = function (obj, props) { + for (var propName in props) { + if (props.hasOwnProperty(propName)) { + if (obj[propName]) + return true; + } + } + + return false; +}; + +$generatorCommon.mainComment = function mainComment() { + return 'This configuration was generated by Ignite Control Center (' + _formatDate(new Date()) + ')'; +}; + +$generatorCommon.builder = function () { + var res = []; + + res.deep = 0; + res.lineStart = true; + + res.append = function (s) { + if (this.lineStart) { + for (var i = 0; i < this.deep; i++) + this.push(' '); + + this.lineStart = false; + } + + this.push(s); + + return this; + }; + + res.line = function (s) { + if (s) + this.append(s); + + this.push('\n'); + this.lineStart = true; + + return this; + }; + + res.startBlock = function (s) { + if (s) + this.append(s); + + this.push('\n'); + this.lineStart = true; + this.deep++; + + return this; + }; + + res.endBlock = function (s) { + this.deep--; + + if (s) + this.append(s); + + this.push('\n'); + this.lineStart = true; + + return this; + }; + + res.emptyLineIfNeeded = function () { + if (this.needEmptyLine) { + this.line(); + + this.needEmptyLine = false; + + return true; + } + + return false; + }; + + res.imports = {}; + + res.importClass = function (clsName) { + var fullClassName = $dataStructures.fullClassName(clsName); + + var dotIdx = fullClassName.lastIndexOf('.'); + + var 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; + }; + + /** + * @returns String with "java imports" section. + */ + res.generateImports = function () { + var res = []; + + for (var clsName in this.imports) { + if (this.imports.hasOwnProperty(clsName) && this.imports[clsName].lastIndexOf('java.lang.', 0) != 0) + res.push('import ' + this.imports[clsName] + ';'); + } + + res.sort(); + + return res.join('\n') + }; + + return res; +}; + +function _classDescriptor(className, fields) { + return {className: className, fields: fields} +} + +$generatorCommon.EVICTION_POLICIES = { + LRU: _classDescriptor('org.apache.ignite.cache.eviction.lru.LruEvictionPolicy', + {batchSize: null, maxMemorySize: null, maxSize: null}), + RND: _classDescriptor('org.apache.ignite.cache.eviction.random.RandomEvictionPolicy', + {maxSize: null}), + FIFO: _classDescriptor('org.apache.ignite.cache.eviction.fifo.FifoEvictionPolicy', + {batchSize: null, maxMemorySize: null, maxSize: null}), + SORTED: _classDescriptor('org.apache.ignite.cache.eviction.sorted.SortedEvictionPolicy', + {batchSize: null, maxMemorySize: null, maxSize: null}) +}; + +$generatorCommon.MARSHALLERS = { + OptimizedMarshaller: _classDescriptor('org.apache.ignite.marshaller.optimized.OptimizedMarshaller', + {poolSize: null, requireSerializable: null }), + JdkMarshaller: _classDescriptor('org.apache.ignite.marshaller.jdk.JdkMarshaller', {}) +}; + +$generatorCommon.KNOWN_CLASSES = { + Oracle: _classDescriptor('org.apache.ignite.cache.store.jdbc.dialect.OracleDialect', {}), + DB2: _classDescriptor('org.apache.ignite.cache.store.jdbc.dialect.DB2Dialect', {}), + SQLServer: _classDescriptor('org.apache.ignite.cache.store.jdbc.dialect.SQLServerDialect', {}), + MySQL: _classDescriptor('org.apache.ignite.cache.store.jdbc.dialect.MySQLDialect', {}), + PostgreSQL: _classDescriptor('org.apache.ignite.cache.store.jdbc.dialect.BasicJdbcDialect', {}), + H2: _classDescriptor('org.apache.ignite.cache.store.jdbc.dialect.H2Dialect', {}) +}; + +$generatorCommon.DATA_SOURCES = { + Oracle: 'oracle.jdbc.pool.OracleDataSource', + DB2: 'com.ibm.db2.jcc.DB2ConnectionPoolDataSource', + SQLServer: 'com.microsoft.sqlserver.jdbc.SQLServerDataSource', + MySQL: 'com.mysql.jdbc.jdbc2.optional.MysqlDataSource', + PostgreSQL: 'org.postgresql.ds.PGPoolingDataSource', + H2: 'org.h2.jdbcx.JdbcDataSource' +}; + +$generatorCommon.STORE_FACTORIES = { + CacheJdbcPojoStoreFactory: _classDescriptor('org.apache.ignite.cache.store.jdbc.CacheJdbcPojoStoreFactory', + {dataSourceBean: null, dialect: {type: 'className'}}), + CacheJdbcBlobStoreFactory: _classDescriptor('org.apache.ignite.cache.store.jdbc.CacheJdbcBlobStoreFactory', + {user: null, dataSourceBean: null, initSchema: null, createTableQuery: null, loadQuery: null, insertQuery: null, updateQuery: null, deleteQuery: null}), + CacheHibernateBlobStoreFactory: _classDescriptor('org.apache.ignite.cache.store.hibernate.CacheHibernateBlobStoreFactory', + {hibernateProperties: {type: 'propertiesAsList', propVarName: 'props'}}) +}; + +$generatorCommon.ATOMIC_CONFIGURATION = _classDescriptor('org.apache.ignite.configuration.AtomicConfiguration', + {backups: null, cacheMode: {type: 'enum', enumClass: 'CacheMode'}, atomicSequenceReserveSize: null}); + +$generatorCommon.SWAP_SPACE_SPI = _classDescriptor('org.apache.ignite.spi.swapspace.file.FileSwapSpaceSpi', + {baseDirectory: null, readStripesNumber: null, maximumSparsity: {type: 'float'}, maxWriteQueueSize: null, writeBufferSize: null}); + +$generatorCommon.TRANSACTION_CONFIGURATION = _classDescriptor('org.apache.ignite.configuration.TransactionConfiguration', + { + defaultTxConcurrency: {type: 'enum', enumClass: 'TransactionConcurrency'}, + transactionIsolation: {type: 'TransactionIsolation', setterName: 'defaultTxIsolation'}, + defaultTxTimeout: null, + pessimisticTxLogLinger: null, + pessimisticTxLogSize: null, + txSerializableEnabled: null} +); + +/** + * Generate properties file with properties stubs for stores data sources. + * + * @param cluster Configuration to process. + * @returns {string} Generated content. + */ +$generatorCommon.generateProperties = function (cluster) { + var res = exports.builder(); + + var datasources = []; + + if (cluster.caches && cluster.caches.length > 0) { + _.forEach(cluster.caches, function (cache) { + if (cache.cacheStoreFactory && cache.cacheStoreFactory.kind) { + var storeFactory = cache.cacheStoreFactory[cache.cacheStoreFactory.kind]; + + if (storeFactory.dialect) { + var beanId = storeFactory.dataSourceBean; + + if (!_.contains(datasources, beanId)) { + datasources.push(beanId); + + res.line(beanId + '.jdbc.url=YOUR_JDBC_URL'); + res.line(beanId + '.jdbc.username=YOUR_USER_NAME'); + res.line(beanId + '.jdbc.password=YOUR_PASSWORD'); + res.line(); + } + } + } + }); + } + + if (datasources.length > 0) + return '# ' + mainComment() + '\n\n' + res.join(''); + + return undefined; +}; + +if (typeof window === 'undefined') { + module.exports = $generatorCommon; +} http://git-wip-us.apache.org/repos/asf/ignite/blob/0b72d82a/modules/control-center-web/src/main/js/routes/generator/generator-xml.js ---------------------------------------------------------------------- diff --git a/modules/control-center-web/src/main/js/routes/generator/generator-xml.js b/modules/control-center-web/src/main/js/routes/generator/generator-xml.js new file mode 100644 index 0000000..29959a7 --- /dev/null +++ b/modules/control-center-web/src/main/js/routes/generator/generator-xml.js @@ -0,0 +1,896 @@ +/* + * 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. + */ + +if (typeof window === 'undefined') { + _ = require('lodash'); + + $commonUtils = require('../../helpers/common-utils'); + $dataStructures = require('../../helpers/data-structures'); + $generatorCommon = require('./generator-common'); +} + +function _escape(s) { + if (typeof(s) != 'string') + return s; + + return s.replace(/&/g, '&').replace(//g, '>'); +} + +function _escapeAttr(s) { + if (typeof(s) != 'string') + return s; + + return s.replace(/&/g, '&').replace(/"/g, '"'); +} + +function _addProperty(res, obj, propName, setterName) { + var val = obj[propName]; + + if ($commonUtils.isDefined(val)) + _addElement(res, 'property', 'name', setterName ? setterName : propName, 'value', _escapeAttr(val)); + + return val; +} + +function _addClassNameProperty(res, obj, propName) { + var val = obj[propName]; + + if ($commonUtils.isDefined(val)) + _addElement(res, 'property', 'name', propName, 'value', $generatorCommon.javaBuildInClass(val)); + + return val; +} + +function _addListProperty(res, obj, propName, listType, rowFactory) { + var val = obj[propName]; + + if (val && val.length > 0) { + res.emptyLineIfNeeded(); + + if (!listType) + listType = 'list'; + + if (!rowFactory) + rowFactory = function (val) { + return '' + escape(val) + '' + }; + + res.startBlock(''); + res.startBlock('<' + listType + '>'); + + for (var i = 0; i < val.length; i++) + res.line(rowFactory(val[i])); + + res.endBlock(''); + res.endBlock(''); + } +} + +function _addBeanWithProperties(res, bean, beanPropName, beanClass, props, createBeanAlthoughNoProps) { + if (bean && $commonUtils.hasProperty(bean, props)) { + res.emptyLineIfNeeded(); + res.startBlock(''); + res.startBlock(''); + + for (var propName in props) { + if (props.hasOwnProperty(propName)) { + var descr = props[propName]; + + if (descr) { + if (descr.type == 'list') { + _addListProperty(res, bean, propName, descr.setterName); + } + else if (descr.type == 'className') { + if (bean[propName]) { + res.startBlock(''); + res.line(''); + res.endBlock(''); + } + } + else if (descr.type == 'propertiesAsList') { + var val = bean[propName]; + + if (val && val.length > 0) { + res.startBlock(''); + res.startBlock(''); + + for (var i = 0; i < val.length; i++) { + var nameAndValue = val[i]; + + var eqIndex = nameAndValue.indexOf('='); + if (eqIndex >= 0) { + res.line('' + + escape(nameAndValue.substr(eqIndex + 1)) + ''); + } + } + + res.endBlock(''); + res.endBlock(''); + } + } + else + _addProperty(res, bean, propName, descr.setterName); + } + else + _addProperty(res, bean, propName); + } + } + + res.endBlock(''); + res.endBlock(''); + } + else if (createBeanAlthoughNoProps) { + res.emptyLineIfNeeded(); + res.line(''); + res.line(' '); + res.line(''); + } +} + +function _createEvictionPolicy(res, evictionPolicy, propertyName) { + if (evictionPolicy && evictionPolicy.kind) { + var e = $generatorCommon.evictionPolicies[evictionPolicy.kind]; + + var obj = evictionPolicy[evictionPolicy.kind.toUpperCase()]; + + _addBeanWithProperties(res, obj, propertyName, e.className, e.fields, true); + } +} + +function _addCacheTypeMetadataDatabaseFields(res, meta, fieldProperty) { + var fields = meta[fieldProperty]; + + if (fields && fields.length > 0) { + res.startBlock(''); + + res.startBlock(''); + + _.forEach(fields, function (field) { + res.startBlock(''); + }); + + res.endBlock(''); + res.endBlock(''); + } +} + +function _addCacheTypeMetadataQueryFields(res, meta, fieldProperty) { + var fields = meta[fieldProperty]; + + if (fields && fields.length > 0) { + res.startBlock(''); + + res.startBlock(''); + + _.forEach(fields, function (field) { + _addElement(res, 'entry', 'key', field.name, 'value', $generatorCommon.javaBuildInClass(field.className)); + }); + + res.endBlock(''); + + res.endBlock(''); + } +} + +function _addCacheTypeMetadataGroups(res, meta) { + var groups = meta.groups; + + if (groups && groups.length > 0) { + res.startBlock(''); + res.startBlock(''); + + _.forEach(groups, function (group) { + var fields = group.fields; + + if (fields && fields.length > 0) { + res.startBlock(''); + res.startBlock(''); + + _.forEach(fields, function (field) { + res.startBlock(''); + + res.startBlock(''); + res.line(''); + res.line(''); + res.endBlock(''); + + res.endBlock(''); + }); + + res.endBlock(''); + res.endBlock(''); + } + }); + + res.endBlock(''); + res.endBlock(''); + } +} + +function _generateCacheTypeMetadataConfiguration(res, meta) { + if (!res) + res = $generatorCommon.builder(); + + res.startBlock(''); + + return res; +} + +function _generateCacheConfiguration(res, cacheCfg) { + if (!res) + res = $generatorCommon.builder(); + + res.startBlock(''); + + _addProperty(res, cacheCfg, 'name'); + + res.needEmptyLine = true; + + var cacheMode = _addProperty(res, cacheCfg, 'mode', 'cacheMode'); + + _addProperty(res, cacheCfg, 'atomicityMode'); + + if (cacheMode == 'PARTITIONED') + _addProperty(res, cacheCfg, 'backups'); + + _addProperty(res, cacheCfg, 'readFromBackup'); + + _addProperty(res, cacheCfg, 'startSize'); + + res.needEmptyLine = true; + + _addProperty(res, cacheCfg, 'memoryMode'); + _addProperty(res, cacheCfg, 'offHeapMaxMemory'); + _addProperty(res, cacheCfg, 'swapEnabled'); + _addProperty(res, cacheCfg, 'copyOnRead'); + + res.needEmptyLine = true; + + _createEvictionPolicy(res, cacheCfg.evictionPolicy, 'evictionPolicy'); + + res.needEmptyLine = true; + + if (cacheCfg.nearCacheEnabled) { + res.emptyLineIfNeeded(); + + res.startBlock(''); + res.startBlock(''); + + if (cacheCfg.nearConfiguration && cacheCfg.nearConfiguration.nearStartSize) + _addProperty(res, cacheCfg.nearConfiguration, 'nearStartSize'); + + if (cacheCfg.nearConfiguration && cacheCfg.nearConfiguration.nearEvictionPolicy.kind) + _createEvictionPolicy(res, cacheCfg.nearConfiguration.nearEvictionPolicy, 'nearEvictionPolicy'); + + res.endBlock(''); + res.endBlock(''); + } + + res.needEmptyLine = true; + + _addProperty(res, cacheCfg, 'sqlEscapeAll'); + _addProperty(res, cacheCfg, 'sqlOnheapRowCacheSize'); + _addProperty(res, cacheCfg, 'longQueryWarningTimeout'); + + if (cacheCfg.indexedTypes && cacheCfg.indexedTypes.length > 0) { + res.startBlock(''); + res.startBlock(''); + + for (var i = 0; i < cacheCfg.indexedTypes.length; i++) { + var pair = cacheCfg.indexedTypes[i]; + + res.line('' + $generatorCommon.javaBuildInClass(pair.keyClass) + ''); + res.line('' + $generatorCommon.javaBuildInClass(pair.valueClass) + ''); + } + + res.endBlock(''); + res.endBlock(''); + } + + _addListProperty(res, cacheCfg, 'sqlFunctionClasses', 'array'); + + res.needEmptyLine = true; + + if (cacheMode != 'LOCAL') { + _addProperty(res, cacheCfg, 'rebalanceMode'); + _addProperty(res, cacheCfg, 'rebalanceThreadPoolSize'); + _addProperty(res, cacheCfg, 'rebalanceBatchSize'); + _addProperty(res, cacheCfg, 'rebalanceOrder'); + _addProperty(res, cacheCfg, 'rebalanceDelay'); + _addProperty(res, cacheCfg, 'rebalanceTimeout'); + _addProperty(res, cacheCfg, 'rebalanceThrottle'); + + res.needEmptyLine = true; + } + + if (cacheCfg.cacheStoreFactory && cacheCfg.cacheStoreFactory.kind) { + var storeFactory = cacheCfg.cacheStoreFactory[cacheCfg.cacheStoreFactory.kind]; + var data = $generatorCommon.STORE_FACTORIES[cacheCfg.cacheStoreFactory.kind]; + + _addBeanWithProperties(res, storeFactory, 'cacheStoreFactory', data.className, data.fields, true); + + if (storeFactory.dialect) { + if (_.findIndex(res.datasources, function (ds) { + return ds.dataSourceBean == storeFactory.dataSourceBean; + }) < 0) { + res.datasources.push({ + dataSourceBean: storeFactory.dataSourceBean, + className: $generatorCommon.DATA_SOURCES[storeFactory.dialect] + }); + } + } + } + + res.needEmptyLine = true; + + _addProperty(res, cacheCfg, 'loadPreviousValue'); + _addProperty(res, cacheCfg, 'readThrough'); + _addProperty(res, cacheCfg, 'writeThrough'); + + res.needEmptyLine = true; + + _addProperty(res, cacheCfg, 'invalidate'); + _addProperty(res, cacheCfg, 'defaultLockTimeout'); + _addProperty(res, cacheCfg, 'transactionManagerLookupClassName'); + + res.needEmptyLine = true; + + _addProperty(res, cacheCfg, 'writeBehindEnabled'); + _addProperty(res, cacheCfg, 'writeBehindBatchSize'); + _addProperty(res, cacheCfg, 'writeBehindFlushSize'); + _addProperty(res, cacheCfg, 'writeBehindFlushFrequency'); + _addProperty(res, cacheCfg, 'writeBehindFlushThreadCount'); + + res.needEmptyLine = true; + + _addProperty(res, cacheCfg, 'statisticsEnabled'); + _addProperty(res, cacheCfg, 'managementEnabled'); + + res.needEmptyLine = true; + + _addProperty(res, cacheCfg, 'maxConcurrentAsyncOperations'); + + // Generate cache type metadata configs. + if ((cacheCfg.queryMetadata && cacheCfg.queryMetadata.length > 0) || + (cacheCfg.storeMetadata && cacheCfg.storeMetadata.length > 0)) { + res.emptyLineIfNeeded(); + + res.startBlock(''); + res.startBlock(''); + + var metaNames = []; + + if (cacheCfg.queryMetadata && cacheCfg.queryMetadata.length > 0) { + _.forEach(cacheCfg.queryMetadata, function (meta) { + if (!_.contains(metaNames, meta.name)) { + metaNames.push(meta.name); + + _generateCacheTypeMetadataConfiguration(res, meta); + } + }); + } + + if (cacheCfg.storeMetadata && cacheCfg.storeMetadata.length > 0) { + _.forEach(cacheCfg.storeMetadata, function (meta) { + if (!_.contains(metaNames, meta.name)) { + metaNames.push(meta.name); + + _generateCacheTypeMetadataConfiguration(res, meta); + } + }); + } + + res.endBlock(''); + res.endBlock(''); + } + + res.endBlock(''); + + return res; +} + +function _addElement(res, tag, attr1, val1, attr2, val2) { + var elem = '<' + tag; + + if (attr1) { + elem += ' ' + attr1 + '="' + val1 + '"' + } + + if (attr2) { + elem += ' ' + attr2 + '="' + val2 + '"' + } + + elem += '/>'; + + res.emptyLineIfNeeded(); + res.line(elem); +} + +$generatorXml = {}; + +$generatorXml.general = function (cluster, res) { + if (!res) + res = $generatorCommon.builder(); + + // Generate discovery. + if (cluster.discovery) { + res.startBlock(''); + res.startBlock(''); + res.startBlock(''); + + var d = cluster.discovery; + + switch (d.kind) { + case 'Multicast': + res.startBlock(''); + + _addProperty(res, d.Multicast, 'multicastGroup'); + _addProperty(res, d.Multicast, 'multicastPort'); + _addProperty(res, d.Multicast, 'responseWaitTime'); + _addProperty(res, d.Multicast, 'addressRequestAttempts'); + _addProperty(res, d.Multicast, 'localAddress'); + + res.endBlock(''); + + break; + + case 'Vm': + if (d.Vm.addresses.length > 0) { + res.startBlock(''); + + _addListProperty(res, d.Vm, 'addresses'); + + res.endBlock(''); + } + else { + res.line(''); + } + + break; + + case 'S3': + res.startBlock(''); + + if (d.S3 && d.S3.bucketName) + res.line(''); + + res.endBlock(''); + + break; + + case 'Cloud': + res.startBlock(''); + + _addProperty(res, d.Cloud, 'credential'); + _addProperty(res, d.Cloud, 'credentialPath'); + _addProperty(res, d.Cloud, 'identity'); + _addProperty(res, d.Cloud, 'provider'); + _addListProperty(res, d.Cloud, 'regions'); + _addListProperty(res, d.Cloud, 'zones'); + + res.endBlock(''); + + break; + + case 'GoogleStorage': + res.startBlock(''); + + _addProperty(res, d.GoogleStorage, 'projectName'); + _addProperty(res, d.GoogleStorage, 'bucketName'); + _addProperty(res, d.GoogleStorage, 'serviceAccountP12FilePath'); + _addProperty(res, d.GoogleStorage, 'serviceAccountId'); + + //if (d.GoogleStorage.addrReqAttempts) todo ???? + // res.line(''); + + res.endBlock(''); + + break; + + case 'Jdbc': + res.startBlock(''); + res.line(''); + res.endBlock(''); + + break; + + case 'SharedFs': + if (d.SharedFs.path) { + res.startBlock(''); + _addProperty(res, d.SharedFs, 'path'); + res.endBlock(''); + } + else { + res.line(''); + } + + break; + + default: + throw "Unknown discovery kind: " + d.kind; + } + + res.endBlock(''); + res.endBlock(''); + res.endBlock(''); + + res.needEmptyLine = true; + } + + return res; +}; + +// Generate atomics group. +$generatorXml.atomics = function (cluster, res) { + if (!res) + res = $generatorCommon.builder(); + + var atomicCfg = $generatorCommon.ATOMIC_CONFIGURATION; + + _addBeanWithProperties(res, cluster.atomicConfiguration, 'atomicConfiguration', atomicCfg.className, atomicCfg.fields); + + res.needEmptyLine = true; + + return res; +}; + +// Generate communication group. +$generatorXml.communication = function (cluster, res) { + if (!res) + res = $generatorCommon.builder(); + + _addProperty(res, cluster, 'networkTimeout'); + _addProperty(res, cluster, 'networkSendRetryDelay'); + _addProperty(res, cluster, 'networkSendRetryCount'); + _addProperty(res, cluster, 'segmentCheckFrequency'); + _addProperty(res, cluster, 'waitForSegmentOnStart'); + _addProperty(res, cluster, 'discoveryStartupDelay'); + + res.needEmptyLine = true; + + return res; +}; + +// Generate deployment group. +$generatorXml.deployment = function (cluster, res) { + if (!res) + res = $generatorCommon.builder(); + + _addProperty(res, cluster, 'deploymentMode'); + + res.needEmptyLine = true; + + return res; +}; + +// Generate events group. +$generatorXml.events = function (cluster, res) { + if (!res) + res = $generatorCommon.builder(); + + if (cluster.includeEventTypes && cluster.includeEventTypes.length > 0) { + res.emptyLineIfNeeded(); + + res.startBlock(''); + + if (cluster.includeEventTypes.length == 1) + res.line(''); + else { + res.startBlock(''); + + for (i = 0; i < cluster.includeEventTypes.length; i++) { + if (i > 0) + res.line(); + + var eventGroup = cluster.includeEventTypes[i]; + + res.line(''); + + var eventList = $dataStructures.EVENT_GROUPS[eventGroup]; + + for (var k = 0; k < eventList.length; k++) { + res.line('') + } + } + + res.endBlock(''); + } + + res.endBlock(''); + + res.needEmptyLine = true; + } + + return res; +}; + +// Generate marshaller group. +$generatorXml.marshaller = function (cluster, res) { + if (!res) + res = $generatorCommon.builder(); + + var marshaller = cluster.marshaller; + + if (marshaller && marshaller.kind) { + var marshallerDesc = $generatorCommon.MARSHALLERS[marshaller.kind]; + + _addBeanWithProperties(res, marshaller[marshaller.kind], 'marshaller', marshallerDesc.className, marshallerDesc.fields, true); + + res.needEmptyLine = true; + } + + _addProperty(res, cluster, 'marshalLocalJobs'); + _addProperty(res, cluster, 'marshallerCacheKeepAliveTime'); + _addProperty(res, cluster, 'marshallerCacheThreadPoolSize'); + + res.needEmptyLine = true; + + return res; +}; + +// Generate metrics group. +$generatorXml.metrics = function (cluster, res) { + if (!res) + res = $generatorCommon.builder(); + + _addProperty(res, cluster, 'metricsExpireTime'); + _addProperty(res, cluster, 'metricsHistorySize'); + _addProperty(res, cluster, 'metricsLogFrequency'); + _addProperty(res, cluster, 'metricsUpdateFrequency'); + + res.needEmptyLine = true; + + return res; +}; + +// Generate PeerClassLoading group. +$generatorXml.p2p = function (cluster, res) { + if (!res) + res = $generatorCommon.builder(); + + _addProperty(res, cluster, 'peerClassLoadingEnabled'); + _addListProperty(res, cluster, 'peerClassLoadingLocalClassPathExclude'); + _addProperty(res, cluster, 'peerClassLoadingMissedResourcesCacheSize'); + _addProperty(res, cluster, 'peerClassLoadingThreadPoolSize'); + + res.needEmptyLine = true; + + return res; +}; + +// Generate swap group. +$generatorXml.swap = function (cluster, res) { + if (!res) + res = $generatorCommon.builder(); + + var swapSpaceSpi = $generatorCommon.SWAP_SPACE_SPI; + + if (cluster.swapSpaceSpi && cluster.swapSpaceSpi.kind == 'FileSwapSpaceSpi') { + _addBeanWithProperties(res, cluster.swapSpaceSpi.FileSwapSpaceSpi, 'swapSpaceSpi', + swapSpaceSpi.className, swapSpaceSpi.fields, true); + + res.needEmptyLine = true; + } + + return res; +}; + +// Generate time group. +$generatorXml.time = function (cluster, res) { + if (!res) + res = $generatorCommon.builder(); + + _addProperty(res, cluster, 'clockSyncSamples'); + _addProperty(res, cluster, 'clockSyncFrequency'); + _addProperty(res, cluster, 'timeServerPortBase'); + _addProperty(res, cluster, 'timeServerPortRange'); + + res.needEmptyLine = true; + + return res; +}; + +// Generate thread pools group. +$generatorXml.pools = function (cluster, res) { + if (!res) + res = $generatorCommon.builder(); + + _addProperty(res, cluster, 'publicThreadPoolSize'); + _addProperty(res, cluster, 'systemThreadPoolSize'); + _addProperty(res, cluster, 'managementThreadPoolSize'); + _addProperty(res, cluster, 'igfsThreadPoolSize'); + res.needEmptyLine = true; + + return res; +}; + +// Generate transactions group. +$generatorXml.transactions = function (cluster, res) { + if (!res) + res = $generatorCommon.builder(); + + var trnCfg = $generatorCommon.TRANSACTION_CONFIGURATION; + + _addBeanWithProperties(res, cluster.transactionConfiguration, 'transactionConfiguration', trnCfg.className, trnCfg.fields); + + res.needEmptyLine = true; + + return res; +}; + +$generatorXml.clusterConfiguration = function (cluster, clientNearConfiguration) { + var res = $generatorCommon.builder(); + + res.datasources = []; + res.deep = 1; + + if (clientNearConfiguration) { + res.startBlock(''); + + if (clientNearConfiguration.nearStartSize) + _addProperty(res, clientNearConfiguration, 'nearStartSize'); + + if (clientNearConfiguration.nearEvictionPolicy && clientNearConfiguration.nearEvictionPolicy.kind) + _createEvictionPolicy(res, clientNearConfiguration.nearEvictionPolicy, 'nearEvictionPolicy'); + + res.endBlock(''); + + res.line(); + } + + // Generate Ignite Configuration. + res.startBlock(''); + + if (clientNearConfiguration) { + res.line(''); + + res.line(); + } + + $generatorXml.general(cluster, res); + + $generatorXml.atomics(cluster, res); + + $generatorXml.communication(cluster, res); + + $generatorXml.deployment(cluster, res); + + $generatorXml.events(cluster, res); + + $generatorXml.marshaller(cluster, res); + + $generatorXml.metrics(cluster, res); + + $generatorXml.p2p(cluster, res); + + $generatorXml.swap(cluster, res); + + $generatorXml.time(cluster, res); + + $generatorXml.pools(cluster, res); + + $generatorXml.transactions(cluster, res); + + // Generate caches configs. + if (cluster.caches && cluster.caches.length > 0) { + res.emptyLineIfNeeded(); + + res.startBlock(''); + res.startBlock(''); + + for (var i = 0; i < cluster.caches.length; i++) { + if (i > 0) + res.line(); + + var cache = cluster.caches[i]; + + _generateCacheConfiguration(res, cache); + } + + res.endBlock(''); + res.endBlock(''); + + res.needEmptyLine = true; + } + + res.endBlock(''); + + // Build final XML: + // 1. Add header. + var xml = '\n\n'; + + xml += '\n'; + xml += ' 0) { + xml += ' \n'; + xml += ' \n'; + xml += ' \n'; + xml += ' \n\n'; + + xml += ' \n'; + + _.forEach(res.datasources, function (item) { + var beanId = item.dataSourceBean; + + xml += ' \n'; + xml += ' \n'; + xml += ' \n'; + xml += ' \n'; + xml += ' \n\n'; + }); + } + + // 3. Add main content. + xml += res.join(''); + + // 4. Add footer. + xml += '\n'; + + return xml; +}; + +if (typeof window === 'undefined') { + module.exports = $generatorXml; +}