/**
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for
* license information.
*/
package com.microsoft.azure.management.sql.implementation;
import com.microsoft.azure.management.apigeneration.LangDefinition;
import com.microsoft.azure.management.resources.fluentcore.arm.collection.implementation.ReadableWrappersImpl;
import com.microsoft.azure.management.resources.fluentcore.arm.models.implementation.GroupableResourceImpl;
import com.microsoft.azure.management.resources.fluentcore.model.Creatable;
import com.microsoft.azure.management.resources.fluentcore.model.Indexable;
import com.microsoft.azure.management.resources.fluentcore.utils.ListToMapConverter;
import com.microsoft.azure.management.resources.fluentcore.utils.PagedListConverter;
import com.microsoft.azure.management.resources.fluentcore.utils.SdkContext;
import com.microsoft.azure.management.resources.fluentcore.utils.Utils;
import com.microsoft.azure.management.sql.ElasticPoolEditions;
import com.microsoft.azure.management.sql.RecommendedElasticPool;
import com.microsoft.azure.management.sql.ServerMetric;
import com.microsoft.azure.management.sql.ServerVersion;
import com.microsoft.azure.management.sql.ServiceObjective;
import com.microsoft.azure.management.sql.SqlDatabase;
import com.microsoft.azure.management.sql.SqlElasticPool;
import com.microsoft.azure.management.sql.SqlFirewallRule;
import com.microsoft.azure.management.sql.SqlServer;
import rx.Completable;
import rx.Observable;
import rx.functions.Func1;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Implementation for SqlServer and its parent interfaces.
*/
@LangDefinition
public class SqlServerImpl
extends
GroupableResourceImpl<
SqlServer,
ServerInner,
SqlServerImpl,
SqlServerManager>
implements
SqlServer,
SqlServer.Definition,
SqlServer.Update {
private final Map<String, SqlElasticPool.DefinitionStages.WithCreate> elasticPoolCreatableMap;
private final Map<String, SqlFirewallRule.DefinitionStages.WithCreate> firewallRuleCreatableMap;
private final Map<String, SqlDatabase.DefinitionStages.WithAllDifferentOptions> databaseCreatableMap;
private FirewallRulesImpl firewallRulesImpl;
private ElasticPoolsImpl elasticPoolsImpl;
private DatabasesImpl databasesImpl;
private final List<String> elasticPoolsToDelete;
private final List<String> firewallRulesToDelete;
private final List<String> databasesToDelete;
protected SqlServerImpl(String name, ServerInner innerObject, SqlServerManager manager) {
super(name, innerObject, manager);
this.databaseCreatableMap = new HashMap<>();
this.elasticPoolCreatableMap = new HashMap<>();
this.firewallRuleCreatableMap = new HashMap<>();
this.elasticPoolsToDelete = new ArrayList<>();
this.databasesToDelete = new ArrayList<>();
this.firewallRulesToDelete = new ArrayList<>();
}
@Override
protected Observable<ServerInner> getInnerAsync() {
return this.manager().inner().servers().getByResourceGroupAsync(
this.resourceGroupName(), this.name());
}
@Override
public Observable<SqlServer> createResourceAsync() {
final SqlServer self = this;
return this.manager().inner().servers().createOrUpdateAsync(this.resourceGroupName(), this.name(), this.inner())
.map(new Func1<ServerInner, SqlServer>() {
@Override
public SqlServer call(ServerInner serverInner) {
setInner(serverInner);
deleteChildResources();
createOrUpdateChildResources();
return self;
}
});
}
@Override
public String fullyQualifiedDomainName() {
return this.inner().fullyQualifiedDomainName();
}
@Override
public ServerVersion version() {
return this.inner().version();
}
@Override
public String administratorLogin() {
return this.inner().administratorLogin();
}
@Override
public FirewallRules firewallRules() {
if (this.firewallRulesImpl == null) {
this.firewallRulesImpl = new FirewallRulesImpl(this.manager(), this.resourceGroupName(), this.name());
}
return this.firewallRulesImpl;
}
@Override
public ElasticPools elasticPools() {
if (this.elasticPoolsImpl == null) {
this.elasticPoolsImpl = new ElasticPoolsImpl(
this.manager(),
(DatabasesImpl) this.databases(),
this.resourceGroupName(),
this.name(),
this.region());
}
return this.elasticPoolsImpl;
}
@Override
public Databases databases() {
if (this.databasesImpl == null) {
this.databasesImpl = new DatabasesImpl(
this.manager(),
this.resourceGroupName(),
this.name(),
this.region());
}
return this.databasesImpl;
}
@Override
public List<ServerMetric> listUsages() {
PagedListConverter<ServerMetricInner, ServerMetric> converter = new PagedListConverter<ServerMetricInner, ServerMetric>() {
@Override
public ServerMetric typeConvert(ServerMetricInner serverMetricInner) {
return new ServerMetricImpl(serverMetricInner);
}
};
return converter.convert(ReadableWrappersImpl.convertToPagedList(
this.manager().inner().servers().listUsages(
this.resourceGroupName(),
this.name())));
}
@Override
public List<ServiceObjective> listServiceObjectives() {
final ServersInner innerCollection = this.manager().inner().servers();
PagedListConverter<ServiceObjectiveInner, ServiceObjective> converter = new PagedListConverter<ServiceObjectiveInner, ServiceObjective>() {
@Override
public ServiceObjective typeConvert(ServiceObjectiveInner serviceObjectiveInner) {
return new ServiceObjectiveImpl(serviceObjectiveInner, innerCollection);
}
};
return converter.convert(ReadableWrappersImpl.convertToPagedList(
this.manager().inner().servers().listServiceObjectives(
this.resourceGroupName(),
this.name())));
}
@Override
public ServiceObjective getServiceObjective(String serviceObjectiveName) {
return new ServiceObjectiveImpl(
this.manager().inner().servers().getServiceObjective(this.resourceGroupName(), this.name(), serviceObjectiveName),
this.manager().inner().servers());
}
@Override
public Map<String, RecommendedElasticPool> listRecommendedElasticPools() {
final SqlServerImpl self = this;
ListToMapConverter<RecommendedElasticPool, RecommendedElasticPoolInner> converter = new ListToMapConverter<RecommendedElasticPool, RecommendedElasticPoolInner>() {
@Override
protected String name(RecommendedElasticPoolInner recommendedElasticPoolInner) {
return recommendedElasticPoolInner.name();
}
@Override
protected RecommendedElasticPool impl(RecommendedElasticPoolInner recommendedElasticPoolInner) {
return new RecommendedElasticPoolImpl(
recommendedElasticPoolInner,
self.manager());
}
};
return converter.convertToUnmodifiableMap(this.manager().inner().recommendedElasticPools().list(
this.resourceGroupName(),
this.name()));
}
@Override
public SqlServerImpl withAdministratorLogin(String administratorLogin) {
this.inner().withAdministratorLogin(administratorLogin);
return this;
}
@Override
public SqlServerImpl withAdministratorPassword(String administratorLoginPassword) {
this.inner().withAdministratorLoginPassword(administratorLoginPassword);
return this;
}
@Override
public SqlServerManager manager() {
return this.myManager;
}
@Override
public SqlServerImpl withNewDatabase(String databaseName) {
this.databaseCreatableMap.remove(databaseName);
this.databaseCreatableMap.put(databaseName,
this.databases().define(databaseName));
return this;
}
@Override
public SqlServerImpl withoutDatabase(String databaseName) {
this.databasesToDelete.add(databaseName);
return this;
}
@Override
public SqlServerImpl withNewElasticPool(String elasticPoolName, ElasticPoolEditions elasticPoolEdition, String... databaseNames) {
if (this.elasticPoolCreatableMap.get(elasticPoolName) == null) {
this.elasticPoolCreatableMap.put(elasticPoolName, this.elasticPools().define(elasticPoolName).withEdition(elasticPoolEdition));
}
if (databaseNames != null) {
for (String databaseName : databaseNames) {
this.withDatabaseInElasticPool(databaseName, elasticPoolName);
}
}
return this;
}
@Override
public SqlServerImpl withNewElasticPool(String elasticPoolName, ElasticPoolEditions elasticPoolEdition) {
return withNewElasticPool(elasticPoolName, elasticPoolEdition, (String[]) null);
}
@Override
public SqlServerImpl withoutElasticPool(String elasticPoolName) {
this.elasticPoolsToDelete.add(elasticPoolName);
return this;
}
private void withDatabaseInElasticPool(String databaseName, String elasticPoolName) {
this.databaseCreatableMap.remove(databaseName);
this.databaseCreatableMap.put(databaseName,
(SqlDatabase.DefinitionStages.WithAllDifferentOptions) this.databases().define(databaseName)
.withExistingElasticPool(elasticPoolName));
}
@Override
public SqlServerImpl withNewFirewallRule(String ipAddress) {
return this.withNewFirewallRule(ipAddress, ipAddress);
}
@Override
public SqlServerImpl withNewFirewallRule(String startIPAddress, String endIPAddress) {
return this.withNewFirewallRule(startIPAddress, endIPAddress, SdkContext.randomResourceName("firewall_", 15));
}
@Override
public SqlServerImpl withNewFirewallRule(String startIPAddress, String endIPAddress, String firewallRuleName) {
this.firewallRuleCreatableMap.remove(firewallRuleName);
this.firewallRuleCreatableMap.put(firewallRuleName,
this.firewallRules().define(firewallRuleName).withIPAddressRange(startIPAddress, endIPAddress));
return this;
}
@Override
public SqlServerImpl withoutFirewallRule(String firewallRuleName) {
this.firewallRulesToDelete.add(firewallRuleName);
return this;
}
private Observable<Indexable> createOrUpdateFirewallRulesAsync() {
final SqlServerImpl self = this;
if (this.firewallRuleCreatableMap.size() > 0) {
return Utils.rootResource(this.firewallRulesImpl
.sqlFirewallRules()
.createAsync(new ArrayList<Creatable<SqlFirewallRule>>(this.firewallRuleCreatableMap.values())))
.map(new Func1<Indexable, Indexable>() {
@Override
public Indexable call(Indexable indexable) {
self.firewallRuleCreatableMap.clear();
return indexable;
}
});
}
return Observable.empty();
}
private Observable<Indexable> createOrUpdateElasticPoolsAndDatabasesAsync() {
if (this.elasticPoolCreatableMap.size() > 0) {
this.elasticPoolsImpl.elasticPools().create(new ArrayList<Creatable<SqlElasticPool>>(this.elasticPoolCreatableMap.values()));
this.elasticPoolCreatableMap.clear();
}
final SqlServerImpl self = this;
if (this.databaseCreatableMap.size() > 0) {
return Utils.rootResource(this.databasesImpl
.databases()
.createAsync(new ArrayList<Creatable<SqlDatabase>>(this.databaseCreatableMap.values())))
.map(new Func1<Indexable, Indexable>() {
@Override
public Indexable call(Indexable indexable) {
self.databaseCreatableMap.clear();
return indexable;
}
});
}
return Observable.empty();
}
private void createOrUpdateChildResources() {
Observable<Indexable> createFirewallRules = createOrUpdateFirewallRulesAsync();
Observable<Indexable> createDatabases = createOrUpdateElasticPoolsAndDatabasesAsync();
Observable.merge(createFirewallRules, createDatabases).defaultIfEmpty(null).toBlocking().last();
}
private void deleteChildResources() {
Completable deleteFirewallRules = deleteFirewallRule();
Completable deleteDatabasesAndElasticPools = deleteDatabasesAndElasticPools();
Completable.merge(deleteFirewallRules, deleteDatabasesAndElasticPools).await();
}
private Completable deleteDatabasesAndElasticPools() {
List<Completable> deleteDBList = new ArrayList<>();
for (String databaseName : this.databasesToDelete) {
deleteDBList.add(this.databases().deleteAsync(databaseName));
}
Completable deleteDBs = Completable.merge(deleteDBList);
List<Completable> deleteElasticPoolList = new ArrayList<>();
for (String elasticPoolName : this.elasticPoolsToDelete) {
deleteElasticPoolList.add(this.elasticPools().deleteAsync(elasticPoolName));
}
Completable deletePools = Completable.merge(deleteElasticPoolList);
return Completable.concat(deleteDBs, deletePools);
}
private Completable deleteFirewallRule() {
List<Completable> deleteTaskList = new ArrayList<>();
for (String firewallRuleName : this.firewallRulesToDelete) {
deleteTaskList.add(this.firewallRules().deleteAsync(firewallRuleName));
}
return Completable.merge(deleteTaskList);
}
}