diff --git a/azure-mgmt-compute/src/main/java/com/microsoft/azure/management/compute/implementation/AvailabilitySetImpl.java b/azure-mgmt-compute/src/main/java/com/microsoft/azure/management/compute/implementation/AvailabilitySetImpl.java index eb90fcea6a98..a5e161e544a7 100644 --- a/azure-mgmt-compute/src/main/java/com/microsoft/azure/management/compute/implementation/AvailabilitySetImpl.java +++ b/azure-mgmt-compute/src/main/java/com/microsoft/azure/management/compute/implementation/AvailabilitySetImpl.java @@ -8,8 +8,8 @@ import com.microsoft.azure.SubResource; import com.microsoft.azure.management.compute.AvailabilitySet; import com.microsoft.azure.management.compute.InstanceViewStatus; +import com.microsoft.azure.management.resources.fluentcore.arm.models.Resource; import com.microsoft.azure.management.resources.fluentcore.arm.models.implementation.GroupableResourceImpl; -import com.microsoft.azure.management.resources.fluentcore.utils.Utils; import com.microsoft.rest.ServiceCall; import com.microsoft.rest.ServiceCallback; import com.microsoft.rest.ServiceResponse; @@ -101,28 +101,32 @@ public ServiceCall applyAsync(ServiceCallback callback) { return this.createAsync(callback); } + // CreatorTaskGroup.ResourceCreator implementation + @Override - protected void createResource() throws Exception { + public Resource createResource() throws Exception { ServiceResponse response = this.client.createOrUpdate(this.resourceGroupName(), this.name(), this.inner()); - AvailabilitySetInner availabilitySetInner = response.getBody(); - this.setInner(availabilitySetInner); + this.setInner(response.getBody()); this.idOfVMsInSet = null; + return this; } @Override - protected ServiceCall createResourceAsync(final ServiceCallback callback) { + public ServiceCall createResourceAsync(final ServiceCallback callback) { + final AvailabilitySetImpl self = this; return this.client.createOrUpdateAsync(this.resourceGroupName(), this.name(), this.inner(), - Utils.fromVoidCallback(this, new ServiceCallback() { + new ServiceCallback() { @Override public void failure(Throwable t) { callback.failure(t); } @Override - public void success(ServiceResponse result) { + public void success(ServiceResponse response) { + self.setInner(response.getBody()); idOfVMsInSet = null; - callback.success(result); + callback.success(new ServiceResponse(self, response.getResponse())); } - })); + }); } } diff --git a/azure-mgmt-compute/src/main/java/com/microsoft/azure/management/compute/implementation/VirtualMachineImpl.java b/azure-mgmt-compute/src/main/java/com/microsoft/azure/management/compute/implementation/VirtualMachineImpl.java index 513b9b859616..3aebfb4401b2 100644 --- a/azure-mgmt-compute/src/main/java/com/microsoft/azure/management/compute/implementation/VirtualMachineImpl.java +++ b/azure-mgmt-compute/src/main/java/com/microsoft/azure/management/compute/implementation/VirtualMachineImpl.java @@ -40,11 +40,11 @@ import com.microsoft.azure.management.network.PublicIpAddress; import com.microsoft.azure.management.network.implementation.NetworkManager; import com.microsoft.azure.management.resources.fluentcore.arm.ResourceUtils; +import com.microsoft.azure.management.resources.fluentcore.arm.models.Resource; 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.utils.PagedListConverter; import com.microsoft.azure.management.resources.fluentcore.utils.ResourceNamer; -import com.microsoft.azure.management.resources.fluentcore.utils.Utils; import com.microsoft.azure.management.resources.implementation.PageImpl; import com.microsoft.azure.management.storage.StorageAccount; import com.microsoft.azure.management.storage.implementation.StorageManager; @@ -853,13 +853,11 @@ public PowerState powerState() { return null; } - /************************************************** - * . - * CreatableImpl::createResource - **************************************************/ + + // CreatorTaskGroup.ResourceCreator implementation @Override - protected void createResource() throws Exception { + public Resource createResource() throws Exception { if (isInCreateMode()) { setOSDiskAndOSProfileDefaults(); setHardwareProfileDefaults(); @@ -874,10 +872,11 @@ protected void createResource() throws Exception { this.setInner(serviceResponse.getBody()); clearCachedRelatedResources(); initializeDataDisks(); + return this; } @Override - protected ServiceCall createResourceAsync(final ServiceCallback callback) { + public ServiceCall createResourceAsync(final ServiceCallback callback) { if (isInCreateMode()) { setOSDiskAndOSProfileDefaults(); setHardwareProfileDefaults(); @@ -896,19 +895,20 @@ public void success(ServiceResponse result) { handleNetworkSettings(); handleAvailabilitySettings(); call.newCall(client.createOrUpdateAsync(resourceGroupName(), vmName, inner(), - Utils.fromVoidCallback(self, new ServiceCallback() { + new ServiceCallback() { @Override public void failure(Throwable t) { callback.failure(t); } @Override - public void success(ServiceResponse result) { + public void success(ServiceResponse response) { + self.setInner(response.getBody()); clearCachedRelatedResources(); initializeDataDisks(); - callback.success(result); + callback.success(new ServiceResponse(self, response.getResponse())); } - })).getCall()); + }).getCall()); } }); return call; diff --git a/azure-mgmt-network/src/main/java/com/microsoft/azure/management/network/implementation/LoadBalancerImpl.java b/azure-mgmt-network/src/main/java/com/microsoft/azure/management/network/implementation/LoadBalancerImpl.java index bf1e13e75b8b..ce9774c2c387 100644 --- a/azure-mgmt-network/src/main/java/com/microsoft/azure/management/network/implementation/LoadBalancerImpl.java +++ b/azure-mgmt-network/src/main/java/com/microsoft/azure/management/network/implementation/LoadBalancerImpl.java @@ -16,9 +16,9 @@ import com.microsoft.azure.management.network.PublicIpAddress; import com.microsoft.azure.management.network.PublicIpAddress.DefinitionStages.WithGroup; import com.microsoft.azure.management.network.SupportsNetworkInterfaces; +import com.microsoft.azure.management.resources.fluentcore.arm.models.Resource; 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.utils.Utils; import com.microsoft.rest.ServiceCall; import com.microsoft.rest.ServiceCallback; import com.microsoft.rest.ServiceResponse; @@ -201,29 +201,44 @@ public LoadBalancerImpl withExistingVirtualMachines(SupportsNetworkInterfaces... // Getters @Override - protected void createResource() throws Exception { + public List publicIpAddressIds() { + List publicIpAddressIds = new ArrayList<>(); + if (this.inner().frontendIPConfigurations() != null) { + for (FrontendIPConfigurationInner frontEndIpConfig : this.inner().frontendIPConfigurations()) { + publicIpAddressIds.add(frontEndIpConfig.publicIPAddress().id()); + } + } + return Collections.unmodifiableList(publicIpAddressIds); + } + + // CreatorTaskGroup.ResourceCreator implementation + + @Override + public Resource createResource() throws Exception { ensureCreationPrerequisites(); ServiceResponse response = this.innerCollection.createOrUpdate(this.resourceGroupName(), this.name(), this.inner()); this.setInner(response.getBody()); - runPostCreationTasks(); + return this; } @Override - protected ServiceCall createResourceAsync(final ServiceCallback callback) { + public ServiceCall createResourceAsync(final ServiceCallback callback) { + final LoadBalancerImpl self = this; ensureCreationPrerequisites(); return this.innerCollection.createOrUpdateAsync(this.resourceGroupName(), this.name(), this.inner(), - Utils.fromVoidCallback(this, new ServiceCallback() { + new ServiceCallback() { @Override public void failure(Throwable t) { callback.failure(t); } @Override - public void success(ServiceResponse result) { - callback.success(result); + public void success(ServiceResponse response) { + self.setInner(response.getBody()); + callback.success(new ServiceResponse(self, response.getResponse())); try { runPostCreationTasks(); } catch (Exception e) { @@ -231,18 +246,6 @@ public void success(ServiceResponse result) { e.printStackTrace(); } } - })); + }); } - - @Override - public List publicIpAddressIds() { - List publicIpAddressIds = new ArrayList<>(); - if (this.inner().frontendIPConfigurations() != null) { - for (FrontendIPConfigurationInner frontEndIpConfig : this.inner().frontendIPConfigurations()) { - publicIpAddressIds.add(frontEndIpConfig.publicIPAddress().id()); - } - } - return Collections.unmodifiableList(publicIpAddressIds); - } - } \ No newline at end of file diff --git a/azure-mgmt-network/src/main/java/com/microsoft/azure/management/network/implementation/NetworkImpl.java b/azure-mgmt-network/src/main/java/com/microsoft/azure/management/network/implementation/NetworkImpl.java index 84fa28307cd3..7c3aa20dcf2a 100644 --- a/azure-mgmt-network/src/main/java/com/microsoft/azure/management/network/implementation/NetworkImpl.java +++ b/azure-mgmt-network/src/main/java/com/microsoft/azure/management/network/implementation/NetworkImpl.java @@ -7,12 +7,11 @@ import com.microsoft.azure.management.network.Network; import com.microsoft.azure.management.network.Subnet; +import com.microsoft.azure.management.resources.fluentcore.arm.models.Resource; import com.microsoft.azure.management.resources.fluentcore.arm.models.implementation.GroupableResourceImpl; -import com.microsoft.azure.management.resources.fluentcore.utils.Utils; import com.microsoft.rest.ServiceCall; import com.microsoft.rest.ServiceCallback; import com.microsoft.rest.ServiceResponse; - import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -175,36 +174,40 @@ private void ensureCreationPrerequisites() { } @Override - protected void createResource() throws Exception { + public SubnetImpl updateSubnet(String name) { + return (SubnetImpl) this.subnets.get(name); + } + + // CreatorTaskGroup.ResourceCreator implementation + + @Override + public Resource createResource() throws Exception { ensureCreationPrerequisites(); ServiceResponse response = this.innerCollection.createOrUpdate(this.resourceGroupName(), this.name(), this.inner()); this.setInner(response.getBody()); initializeSubnetsFromInner(); + return this; } @Override - protected ServiceCall createResourceAsync(final ServiceCallback callback) { + public ServiceCall createResourceAsync(final ServiceCallback callback) { + final NetworkImpl self = this; ensureCreationPrerequisites(); - return this.innerCollection.createOrUpdateAsync(this.resourceGroupName(), this.name(), this.inner(), - Utils.fromVoidCallback(this, new ServiceCallback() { + new ServiceCallback() { @Override public void failure(Throwable t) { callback.failure(t); } @Override - public void success(ServiceResponse result) { + public void success(ServiceResponse response) { + self.setInner(response.getBody()); initializeSubnetsFromInner(); - callback.success(result); + callback.success(new ServiceResponse(self, response.getResponse())); } - })); - } - - @Override - public SubnetImpl updateSubnet(String name) { - return (SubnetImpl) this.subnets.get(name); + }); } } \ No newline at end of file diff --git a/azure-mgmt-network/src/main/java/com/microsoft/azure/management/network/implementation/NetworkInterfaceImpl.java b/azure-mgmt-network/src/main/java/com/microsoft/azure/management/network/implementation/NetworkInterfaceImpl.java index 2c61b57e014f..6430cb61a63b 100644 --- a/azure-mgmt-network/src/main/java/com/microsoft/azure/management/network/implementation/NetworkInterfaceImpl.java +++ b/azure-mgmt-network/src/main/java/com/microsoft/azure/management/network/implementation/NetworkInterfaceImpl.java @@ -347,12 +347,10 @@ public NicIpConfigurationImpl primaryIpConfiguration() { } - /**************************************************. - * CreatableImpl::createResource - **************************************************/ + // CreatorTaskGroup.ResourceCreator implementation @Override - protected void createResource() throws Exception { + public Resource createResource() throws Exception { NetworkSecurityGroup networkSecurityGroup = null; if (creatableNetworkSecurityGroupKey != null) { networkSecurityGroup = (NetworkSecurityGroup) this.createdResource(creatableNetworkSecurityGroupKey); @@ -371,27 +369,30 @@ protected void createResource() throws Exception { this.setInner(response.getBody()); clearCachedRelatedResources(); initializeNicIpConfigurations(); + return this; } @Override - protected ServiceCall createResourceAsync(final ServiceCallback callback) { + public ServiceCall createResourceAsync(final ServiceCallback callback) { + final NetworkInterfaceImpl self = this; NicIpConfigurationImpl.ensureConfigurations(this.nicIpConfigurations); return this.client.createOrUpdateAsync(this.resourceGroupName(), this.nicName, this.inner(), - Utils.fromVoidCallback(this, new ServiceCallback() { + new ServiceCallback() { @Override public void failure(Throwable t) { callback.failure(t); } @Override - public void success(ServiceResponse result) { + public void success(ServiceResponse response) { + self.setInner(response.getBody()); clearCachedRelatedResources(); initializeNicIpConfigurations(); - callback.success(result); + callback.success(new ServiceResponse(self, response.getResponse())); } - })); + }); } /**************************************************. @@ -455,7 +456,7 @@ NetworkInterfaceImpl withIpConfiguration(NicIpConfigurationImpl nicIpConfigurati return this; } - void addToCreatableDependencies(Creatable creatableResource) { + void addToCreatableDependencies(Creatable creatableResource) { super.addCreatableDependency(creatableResource); } diff --git a/azure-mgmt-network/src/main/java/com/microsoft/azure/management/network/implementation/NetworkSecurityGroupImpl.java b/azure-mgmt-network/src/main/java/com/microsoft/azure/management/network/implementation/NetworkSecurityGroupImpl.java index 7f686ca25923..2376a3acc2a6 100644 --- a/azure-mgmt-network/src/main/java/com/microsoft/azure/management/network/implementation/NetworkSecurityGroupImpl.java +++ b/azure-mgmt-network/src/main/java/com/microsoft/azure/management/network/implementation/NetworkSecurityGroupImpl.java @@ -7,8 +7,8 @@ import com.microsoft.azure.management.network.NetworkSecurityGroup; import com.microsoft.azure.management.network.NetworkSecurityRule; +import com.microsoft.azure.management.resources.fluentcore.arm.models.Resource; import com.microsoft.azure.management.resources.fluentcore.arm.models.implementation.GroupableResourceImpl; -import com.microsoft.azure.management.resources.fluentcore.utils.Utils; import com.microsoft.rest.ServiceCall; import com.microsoft.rest.ServiceCallback; import com.microsoft.rest.ServiceResponse; @@ -100,32 +100,6 @@ public ServiceCall applyAsync(ServiceCallback callback) { return createAsync(callback); } - @Override - protected void createResource() throws Exception { - ServiceResponse response = - this.innerCollection.createOrUpdate(this.resourceGroupName(), this.name(), this.inner()); - this.setInner(response.getBody()); - initializeRulesFromInner(); - } - - @Override - protected ServiceCall createResourceAsync(final ServiceCallback callback) { - return this.innerCollection.createOrUpdateAsync(this.resourceGroupName(), this.name(), this.inner(), - Utils.fromVoidCallback(this, new ServiceCallback() { - @Override - public void failure(Throwable t) { - callback.failure(t); - } - - @Override - public void success(ServiceResponse result) { - initializeRulesFromInner(); - callback.success(result); - } - })); - } - - // Setters (fluent) @Override @@ -174,4 +148,34 @@ public List networkInterfaceIds() { } return Collections.unmodifiableList(ids); } + + // CreatorTaskGroup.ResourceCreator implementation + + @Override + public Resource createResource() throws Exception { + ServiceResponse response = + this.innerCollection.createOrUpdate(this.resourceGroupName(), this.name(), this.inner()); + this.setInner(response.getBody()); + initializeRulesFromInner(); + return this; + } + + @Override + public ServiceCall createResourceAsync(final ServiceCallback callback) { + final NetworkSecurityGroupImpl self = this; + return this.innerCollection.createOrUpdateAsync(this.resourceGroupName(), this.name(), this.inner(), + new ServiceCallback() { + @Override + public void failure(Throwable t) { + callback.failure(t); + } + + @Override + public void success(ServiceResponse response) { + self.setInner(response.getBody()); + initializeRulesFromInner(); + callback.success(new ServiceResponse(self, response.getResponse())); + } + }); + } } \ No newline at end of file diff --git a/azure-mgmt-network/src/main/java/com/microsoft/azure/management/network/implementation/PublicIpAddressImpl.java b/azure-mgmt-network/src/main/java/com/microsoft/azure/management/network/implementation/PublicIpAddressImpl.java index 94a4bf4298c9..0178507cd9c3 100644 --- a/azure-mgmt-network/src/main/java/com/microsoft/azure/management/network/implementation/PublicIpAddressImpl.java +++ b/azure-mgmt-network/src/main/java/com/microsoft/azure/management/network/implementation/PublicIpAddressImpl.java @@ -8,8 +8,8 @@ import com.microsoft.azure.management.network.PublicIpAddress; import com.microsoft.azure.management.network.IPAllocationMethod; import com.microsoft.azure.management.network.PublicIPAddressDnsSettings; +import com.microsoft.azure.management.resources.fluentcore.arm.models.Resource; import com.microsoft.azure.management.resources.fluentcore.arm.models.implementation.GroupableResourceImpl; -import com.microsoft.azure.management.resources.fluentcore.utils.Utils; import com.microsoft.rest.ServiceCall; import com.microsoft.rest.ServiceCallback; import com.microsoft.rest.ServiceResponse; @@ -138,8 +138,10 @@ public String leafDomainLabel() { } } + // CreatorTaskGroup.ResourceCreator implementation + @Override - protected void createResource() throws Exception { + public Resource createResource() throws Exception { // Clean up empty DNS settings final PublicIPAddressDnsSettings dnsSettings = this.inner().dnsSettings(); if (dnsSettings != null) { @@ -153,10 +155,12 @@ protected void createResource() throws Exception { ServiceResponse response = this.client.createOrUpdate(this.resourceGroupName(), this.name(), this.inner()); this.setInner(response.getBody()); + return this; } @Override - protected ServiceCall createResourceAsync(ServiceCallback callback) { + public ServiceCall createResourceAsync(final ServiceCallback callback) { + final PublicIpAddressImpl self = this; // Clean up empty DNS settings final PublicIPAddressDnsSettings dnsSettings = this.inner().dnsSettings(); if (dnsSettings != null) { @@ -168,6 +172,17 @@ protected ServiceCall createResourceAsync(ServiceCallback callback) { } return this.client.createOrUpdateAsync(this.resourceGroupName(), this.name(), this.inner(), - Utils.fromVoidCallback(this, callback)); + new ServiceCallback() { + @Override + public void failure(Throwable t) { + callback.failure(t); + } + + @Override + public void success(ServiceResponse response) { + self.setInner(response.getBody()); + callback.success(new ServiceResponse(self, response.getResponse())); + } + }); } } \ No newline at end of file diff --git a/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/fluentcore/arm/models/implementation/GroupableResourceImpl.java b/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/fluentcore/arm/models/implementation/GroupableResourceImpl.java index 11e0d2d357c4..4c31e15b3162 100644 --- a/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/fluentcore/arm/models/implementation/GroupableResourceImpl.java +++ b/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/fluentcore/arm/models/implementation/GroupableResourceImpl.java @@ -10,6 +10,7 @@ import com.microsoft.azure.management.resources.fluentcore.arm.ResourceUtils; import com.microsoft.azure.management.resources.fluentcore.arm.implementation.ManagerBase; import com.microsoft.azure.management.resources.fluentcore.arm.models.GroupableResource; +import com.microsoft.azure.management.resources.fluentcore.arm.models.Resource; import com.microsoft.azure.management.resources.fluentcore.model.Creatable; /** @@ -22,7 +23,7 @@ * @param the service manager type */ public abstract class GroupableResourceImpl< - FluentModelT, + FluentModelT extends Resource, InnerModelT extends com.microsoft.azure.Resource, FluentModelImplT extends GroupableResourceImpl, ManagerT extends ManagerBase> diff --git a/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/fluentcore/arm/models/implementation/ResourceImpl.java b/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/fluentcore/arm/models/implementation/ResourceImpl.java index 3cfecebd100e..89ef131c7789 100644 --- a/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/fluentcore/arm/models/implementation/ResourceImpl.java +++ b/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/fluentcore/arm/models/implementation/ResourceImpl.java @@ -25,11 +25,11 @@ * @param the implementation type of the fluent model type */ public abstract class ResourceImpl< - FluentModelT, + FluentModelT extends Resource, InnerModelT extends com.microsoft.azure.Resource, FluentModelImplT extends ResourceImpl> extends - CreatableUpdatableImpl + CreatableUpdatableImpl implements Resource { diff --git a/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/fluentcore/model/implementation/CreatableImpl.java b/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/fluentcore/model/implementation/CreatableImpl.java index 19ca9ca7db0a..9fef29a05530 100644 --- a/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/fluentcore/model/implementation/CreatableImpl.java +++ b/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/fluentcore/model/implementation/CreatableImpl.java @@ -5,10 +5,7 @@ */ package com.microsoft.azure.management.resources.fluentcore.model.implementation; - -import com.microsoft.azure.management.resources.fluentcore.arm.models.Resource; import com.microsoft.azure.management.resources.fluentcore.model.Creatable; -import com.microsoft.azure.management.resources.fluentcore.utils.Utils; import com.microsoft.rest.ServiceCall; import com.microsoft.rest.ServiceCallback; @@ -18,18 +15,20 @@ * @param the fluent model type representing the creatable resource * @param the model inner type that the fluent model type wraps * @param the fluent model implementation type + * @param the fluent model or one of the base interface of fluent model */ -public abstract class CreatableImpl +public abstract class CreatableImpl extends IndexableRefreshableWrapperImpl - implements CreatableTaskGroup.RootResourceCreator { + implements CreatorTaskGroup.ResourceCreator { + /** - * The group of tasks to create this resource and creatable it depends on. + * The group of tasks to create this resource and it's dependencies. */ - private CreatableTaskGroup creatableTaskGroup; + private CreatorTaskGroup creatorTaskGroup; protected CreatableImpl(String name, InnerModelT innerObject) { super(name, innerObject); - creatableTaskGroup = new CreatableTaskGroup(name, (Creatable) this, this); + creatorTaskGroup = new CreatorTaskGroup<>(name, this); } /** @@ -37,23 +36,15 @@ protected CreatableImpl(String name, InnerModelT innerObject) { * * @param creatableResource the creatable dependency. */ - protected void addCreatableDependency(Creatable creatableResource) { - CreatableTaskGroup childGroup = ((CreatableImpl) creatableResource).creatableTaskGroup; - childGroup.merge(this.creatableTaskGroup); - } - - @Override - public void createRootResource() throws Exception { - this.createResource(); - } - - @Override - public ServiceCall createRootResourceAsync(ServiceCallback callback) { - return this.createResourceAsync(callback); + @SuppressWarnings("unchecked") + protected void addCreatableDependency(Creatable creatableResource) { + CreatorTaskGroup childGroup = + ((CreatorTaskGroup.ResourceCreator) creatableResource).creatorTaskGroup(); + childGroup.merge(this.creatorTaskGroup); } - protected Resource createdResource(String key) { - return this.creatableTaskGroup.taskResult(key); + protected ResourceT createdResource(String key) { + return this.creatorTaskGroup.taskResult(key); } /** @@ -64,33 +55,12 @@ protected Resource createdResource(String key) { */ @SuppressWarnings("unchecked") public FluentModelImplT create() throws Exception { - // This method get's called in two ways: - // 1. User explicitly call Creatable::create requesting creation of the resource. - // 2. Gets called as a part of creating dependent resources for the resource user requested to create in #1. - // - // The creatableTaskGroup of the 'Creatable' on which user called 'create' (#1) is known as the preparer. - // Preparer is the one responsible for preparing the underlying DAG for traversal. - // - // Initially creatableTaskGroup of all creatables as preparer, but as soon as user calls Create in one of - // them (say A::Create) all other creatables that A depends on will be marked as non-preparer. - // - // This achieve two goals: - // - // a. When #2 happens we know group is already prepared and all left is to create the currently requested resource. - // b. User can call 'Create' on any of the creatables not just the ROOT creatable. [ROOT is the one who does not - // have any dependent] - // - // After the creation of each resource in the creatableTaskGroup owned by the user chosen Creatable (#1), each - // sub-creatableTaskGroup of the created resource will be marked back as preparer. Hence user can again call - // Update on any of these resources [which is nothing but equivalent to calling create again] - // - if (creatableTaskGroup.isPreparer()) { - creatableTaskGroup.prepare(); - creatableTaskGroup.execute(); - } else { - createResource(); + if (creatorTaskGroup.isPreparer()) { + creatorTaskGroup.prepare(); + creatorTaskGroup.execute(); + return (FluentModelImplT) this; } - return (FluentModelImplT) this; + throw new IllegalStateException("Internal Error: create can be called only on preparer"); } /** @@ -101,25 +71,17 @@ public FluentModelImplT create() throws Exception { */ @SuppressWarnings("unchecked") public ServiceCall createAsync(ServiceCallback callback) { - if (creatableTaskGroup.isPreparer()) { - creatableTaskGroup.prepare(); - return creatableTaskGroup.executeAsync(Utils.toVoidCallback((FluentModelT) this, callback)); - } else { - return createResourceAsync(Utils.toVoidCallback((FluentModelT) this, callback)); + if (creatorTaskGroup.isPreparer()) { + creatorTaskGroup.prepare(); + return creatorTaskGroup.executeAsync((ServiceCallback) callback); } + throw new IllegalStateException("Internal Error: createAsync can be called only on preparer"); } /** - * Creates this resource. - * - * @throws Exception when anything goes wrong + * @return the task group associated with this creatable. */ - protected abstract void createResource() throws Exception; - - /** - * Creates this resource asynchronously. - * - * @throws Exception when anything goes wrong - */ - protected abstract ServiceCall createResourceAsync(ServiceCallback callback); + public CreatorTaskGroup creatorTaskGroup() { + return this.creatorTaskGroup; + } } diff --git a/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/fluentcore/model/implementation/CreatableTaskGroup.java b/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/fluentcore/model/implementation/CreatableTaskGroup.java deleted file mode 100644 index 980a03a11368..000000000000 --- a/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/fluentcore/model/implementation/CreatableTaskGroup.java +++ /dev/null @@ -1,76 +0,0 @@ -package com.microsoft.azure.management.resources.fluentcore.model.implementation; - -import com.microsoft.azure.TaskGroupBase; -import com.microsoft.azure.TaskItem; -import com.microsoft.azure.management.resources.fluentcore.arm.models.Resource; -import com.microsoft.azure.management.resources.fluentcore.model.Creatable; -import com.microsoft.rest.ServiceCall; -import com.microsoft.rest.ServiceCallback; - -/** - * Type representing a group of creatable tasks and the dependency between them. - */ -public class CreatableTaskGroup extends TaskGroupBase { - - /** - * Represents a type that know how to create the root resource in a CreatableTaskGroup. - */ - interface RootResourceCreator { - /** - * Creates the root resource. - */ - void createRootResource() throws Exception; - - ServiceCall createRootResourceAsync(ServiceCallback serviceCallback); - } - - private final RootResourceCreator rootCreate; - - /** - * Creates CreatableTaskGroup. - * - * @param rootCreatableId the id of the root creatable - * @param rootCreatable represents the root resource creatable that this group want to create ultimately - * @param rootCreate {@link RootResourceCreator} that know how to create the rootCreatable once all the - * dependencies are available - */ - public CreatableTaskGroup(String rootCreatableId, Creatable rootCreatable, RootResourceCreator rootCreate) { - this(rootCreatableId, new CreatableTaskItem(rootCreatable), rootCreate); - } - - /** - * Creates CreatableTaskGroup. - * - * @param key the key of the root task - * @param rootTask represents the root task that this group want to executes ultimately - * @param rootCreate {@link RootResourceCreator} that know how to create the rootCreatable once all the - * dependencies are available - */ - public CreatableTaskGroup(String key, CreatableTaskItem rootTask, RootResourceCreator rootCreate) { - super(key, rootTask); - this.rootCreate = rootCreate; - } - - /** - * Gets a resource created by a creatable task in this group. - *

- * This method can return null if the resource has not yet created that happens if the responsible task - * is not yet selected for execution or it's it progress - * - * @param key the resource id - * @return the created resource - */ - public Resource createdResource(String key) { - return super.taskResult(key); - } - - @Override - public void executeRootTask(TaskItem task) throws Exception { - this.rootCreate.createRootResource(); - } - - @Override - public ServiceCall executeRootTaskAsync(TaskItem task, ServiceCallback callback) { - return this.rootCreate.createRootResourceAsync(callback); - } -} diff --git a/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/fluentcore/model/implementation/CreatableTaskItem.java b/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/fluentcore/model/implementation/CreatableTaskItem.java deleted file mode 100644 index 5b73c47e6b41..000000000000 --- a/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/fluentcore/model/implementation/CreatableTaskItem.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.microsoft.azure.management.resources.fluentcore.model.implementation; - -import com.microsoft.azure.DAGNode; -import com.microsoft.azure.TaskGroup; -import com.microsoft.azure.management.resources.fluentcore.arm.models.Resource; -import com.microsoft.azure.TaskItem; -import com.microsoft.azure.management.resources.fluentcore.model.Creatable; -import com.microsoft.rest.ServiceCall; -import com.microsoft.rest.ServiceCallback; -import com.microsoft.rest.ServiceResponse; - -/** - * Represents a task that creates a resource when executed. - */ -public class CreatableTaskItem implements TaskItem { - private Creatable creatable; - private DAGNode> node; - private Resource created; - - /** - * Creates CreatableTaskItem. - * - * @param creatable the creatable - */ - public CreatableTaskItem(Creatable creatable) { - this.creatable = creatable; - } - - @Override - public Resource result() { - return created; - } - - @Override - public void execute(TaskGroup> taskGroup, DAGNode> node) throws Exception { - if (this.created == null) { - // execute will be called both in update and create scenarios, - // so run the task only if it not not executed already. - this.created = this.creatable.create(); - } - - taskGroup.dag().reportedCompleted(node); - taskGroup.execute(); - } - - @Override - public ServiceCall executeAsync(final TaskGroup> taskGroup, final DAGNode> node, final ServiceCallback callback) { - final CreatableTaskItem self = this; - return ((Creatable) this.creatable).createAsync(new ServiceCallback() { - @Override - public void failure(Throwable t) { - callback.failure(t); - } - - @Override - public void success(ServiceResponse result) { - self.created = result.getBody(); - taskGroup.dag().reportedCompleted(node); - taskGroup.executeAsync(callback); - } - }); - } -} diff --git a/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/fluentcore/model/implementation/CreatableUpdatableImpl.java b/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/fluentcore/model/implementation/CreatableUpdatableImpl.java index 64e8c797c7f5..d63a724e44c2 100644 --- a/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/fluentcore/model/implementation/CreatableUpdatableImpl.java +++ b/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/fluentcore/model/implementation/CreatableUpdatableImpl.java @@ -14,9 +14,10 @@ * @param the fluent model type representing the resource * @param the model inner type that the fluent model type wraps * @param the implementation type of the fluent model + * @param the fluent model or one of the base interface of fluent model */ -public abstract class CreatableUpdatableImpl - extends CreatableImpl { +public abstract class CreatableUpdatableImpl + extends CreatableImpl { protected CreatableUpdatableImpl(String name, InnerModelT innerObject) { super(name, innerObject); diff --git a/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/fluentcore/model/implementation/CreatorTaskGroup.java b/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/fluentcore/model/implementation/CreatorTaskGroup.java new file mode 100644 index 000000000000..a2fe11547ffd --- /dev/null +++ b/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/fluentcore/model/implementation/CreatorTaskGroup.java @@ -0,0 +1,73 @@ +package com.microsoft.azure.management.resources.fluentcore.model.implementation; + +import com.microsoft.azure.TaskGroupBase; +import com.microsoft.rest.ServiceCall; +import com.microsoft.rest.ServiceCallback; + +/** + * Type representing a group of tasks that can create resources that are dependents on each other. + * + * @param the type of the resource this group creates + */ +public class CreatorTaskGroup extends TaskGroupBase { + /** + * Represents a type that know how to create resource. + * + * @param the type of the resource that this creator creates + */ + interface ResourceCreator { + /** + * Creates the resource asynchronously. + * + * @param serviceCallback the callback to be invoked after the creation of resource + * @return the service call reference + */ + ServiceCall createResourceAsync(ServiceCallback serviceCallback); + + /** + * Creates the resource synchronously. + * + * @return the created resource + * @throws Exception + */ + T createResource() throws Exception; + + /** + * @return Gets the task group. + */ + CreatorTaskGroup creatorTaskGroup(); + } + + /** + * Creates CreatorTaskGroup. + * + * @param rootCreatableId the id of the root creatable + * @param resourceCreator represents the resource creator that this group want to create ultimately + */ + public CreatorTaskGroup(String rootCreatableId, ResourceCreator resourceCreator) { + this(rootCreatableId, new CreatorTaskItem<>(resourceCreator)); + } + + /** + * Creates CreatorTaskGroup. + * + * @param key the key of the root task + * @param rootTask represents the root task that this group want to executes ultimately + */ + public CreatorTaskGroup(String key, CreatorTaskItem rootTask) { + super(key, rootTask); + } + + /** + * Gets a resource created by a creator task in this group. + *

+ * This method can return null if the resource has not yet created that happens if the responsible task + * is not yet selected for execution or it's it progress + * + * @param key the resource id + * @return the created resource + */ + public ResourceT createdResource(String key) { + return super.taskResult(key); + } +} diff --git a/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/fluentcore/model/implementation/CreatorTaskItem.java b/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/fluentcore/model/implementation/CreatorTaskItem.java new file mode 100644 index 000000000000..495b6f4612ea --- /dev/null +++ b/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/fluentcore/model/implementation/CreatorTaskItem.java @@ -0,0 +1,56 @@ +package com.microsoft.azure.management.resources.fluentcore.model.implementation; + +import com.microsoft.azure.TaskItem; +import com.microsoft.rest.ServiceCall; +import com.microsoft.rest.ServiceCallback; +import com.microsoft.rest.ServiceResponse; + +/** + * Represents a task that creates a resource when executed. + * + * @param the type of the resource that this task creates + */ +public class CreatorTaskItem implements TaskItem { + private CreatorTaskGroup.ResourceCreator resourceCreator; + private ResourceT created; + + /** + * Creates CreatorTaskItem. + * + * @param resourceCreator the resource creator + */ + public CreatorTaskItem(CreatorTaskGroup.ResourceCreator resourceCreator) { + this.resourceCreator = resourceCreator; + } + + @Override + public ResourceT result() { + return created; + } + + @Override + public void execute() throws Exception { + if (this.created == null) { + // execute will be called both in update and create scenarios, + // so run the task only if it not not executed already. + this.created = this.resourceCreator.createResource(); + } + } + + @Override + public ServiceCall executeAsync(final ServiceCallback callback) { + final CreatorTaskItem self = this; + return (this.resourceCreator).createResourceAsync(new ServiceCallback() { + @Override + public void failure(Throwable t) { + callback.failure(t); + } + + @Override + public void success(ServiceResponse result) { + self.created = result.getBody(); + callback.success(result); + } + }); + } +} diff --git a/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/fluentcore/utils/Utils.java b/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/fluentcore/utils/Utils.java index 379c3a031e26..4983c48f7733 100644 --- a/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/fluentcore/utils/Utils.java +++ b/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/fluentcore/utils/Utils.java @@ -59,10 +59,12 @@ public void success(ServiceResponse result) { * @param callback the void callback * @param the inner resource type * @param the fluent resource type - * @param the implementation for the fuent resource type - * @return the inner callback + * @param the fluent model base type that all fluent models in the same task group derive from + * @param the implementation for the fluent resource type + * + * @return new callback from the void callback */ - public static > ServiceCallback + public static > ServiceCallback fromVoidCallback(final FluentImplT modelImpl, final ServiceCallback callback) { return new ServiceCallback() { @Override diff --git a/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/implementation/DeploymentImpl.java b/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/implementation/DeploymentImpl.java index b2759e9ac2f6..75efbdf35aee 100644 --- a/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/implementation/DeploymentImpl.java +++ b/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/implementation/DeploymentImpl.java @@ -36,7 +36,7 @@ * The implementation of {@link Deployment} and its nested interfaces. */ final class DeploymentImpl extends - CreatableUpdatableImpl + CreatableUpdatableImpl implements Deployment, Deployment.Definition, @@ -182,7 +182,9 @@ public DeploymentExportResult exportTemplate() throws CloudException, IOExceptio @Override public DeploymentImpl withNewResourceGroup(String resourceGroupName, Region region) { - this.creatableResourceGroup = this.resourceManager.resourceGroups().define(resourceGroupName).withRegion(region); + this.creatableResourceGroup = this.resourceManager.resourceGroups() + .define(resourceGroupName) + .withRegion(region); this.resourceGroupName = resourceGroupName; return this; } @@ -190,9 +192,8 @@ public DeploymentImpl withNewResourceGroup(String resourceGroupName, Region regi @Override public DeploymentImpl withNewResourceGroup(Creatable resourceGroupDefinition) { this.resourceGroupName = resourceGroupDefinition.key(); - addCreatableDependency(resourceGroupDefinition); + this.creatableResourceGroup = resourceGroupDefinition; return this; - } @Override @@ -300,28 +301,28 @@ public void failure(Throwable t) { @Override public void success(ServiceResponse result) { - createResourceAsync(new ServiceCallback() { + createResourceAsync(new ServiceCallback() { @Override public void failure(Throwable t) { callback.failure(t); } @Override - public void success(ServiceResponse result) { + public void success(ServiceResponse result) { callback.success(new ServiceResponse<>(self, result.getResponse())); } }); } }); } else { - return createResourceAsync(new ServiceCallback() { + return createResourceAsync(new ServiceCallback() { @Override public void failure(Throwable t) { callback.failure(t); } @Override - public void success(ServiceResponse result) { + public void success(ServiceResponse result) { callback.success(new ServiceResponse<>(self, result.getResponse())); } }); @@ -334,7 +335,7 @@ public Deployment refresh() throws Exception { } @Override - protected void createResource() throws Exception { + public Deployment createResource() throws Exception { DeploymentInner inner = new DeploymentInner() .withProperties(new DeploymentProperties()); inner.properties().withMode(mode()); @@ -343,10 +344,11 @@ protected void createResource() throws Exception { inner.properties().withParameters(parameters()); inner.properties().withParametersLink(parametersLink()); client.createOrUpdate(resourceGroupName(), name(), inner); + return this; } @Override - protected ServiceCall createResourceAsync(final ServiceCallback callback) { + public ServiceCall createResourceAsync(final ServiceCallback callback) { DeploymentInner inner = new DeploymentInner() .withProperties(new DeploymentProperties()); inner.properties().withMode(mode()); @@ -361,8 +363,8 @@ public void failure(Throwable t) { } @Override - public void success(ServiceResponse result) { - callback.success(new ServiceResponse(result.getHeadResponse())); + public void success(ServiceResponse response) { + callback.success(new ServiceResponse(response.getHeadResponse())); } }); } diff --git a/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/implementation/GenericResourceImpl.java b/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/implementation/GenericResourceImpl.java index 94919360fadc..3c7172c00a4c 100644 --- a/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/implementation/GenericResourceImpl.java +++ b/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/implementation/GenericResourceImpl.java @@ -7,11 +7,12 @@ package com.microsoft.azure.management.resources.implementation; import com.microsoft.azure.management.resources.GenericResource; +import com.microsoft.azure.management.resources.fluentcore.arm.models.Resource; import com.microsoft.azure.management.resources.fluentcore.arm.models.implementation.GroupableResourceImpl; -import com.microsoft.azure.management.resources.fluentcore.utils.Utils; import com.microsoft.azure.management.resources.Plan; import com.microsoft.rest.ServiceCall; import com.microsoft.rest.ServiceCallback; +import com.microsoft.rest.ServiceResponse; /** * The implementation for {@link GenericResource} and its nested interfaces. @@ -132,11 +133,33 @@ public GenericResourceImpl create() throws Exception { @Override public ServiceCall createAsync(final ServiceCallback callback) { - return createResourceAsync(Utils.toVoidCallback(this, callback)); + return createResourceAsync(new ServiceCallback() { + @Override + public void failure(Throwable t) { + callback.failure(t); + } + + @Override + public void success(ServiceResponse result) { + callback.success(new ServiceResponse<>((GenericResource) result.getBody(), result.getResponse())); + } + }); + } + + @Override + public GenericResourceImpl apply() throws Exception { + return create(); } @Override - protected void createResource() throws Exception { + public ServiceCall applyAsync(ServiceCallback callback) { + return createAsync(callback); + } + + // CreatorTaskGroup.ResourceCreator implementation + + @Override + public Resource createResource() throws Exception { GenericResourceInner inner = client.createOrUpdate( resourceGroupName(), resourceProviderNamespace, @@ -147,10 +170,12 @@ protected void createResource() throws Exception { inner() ).getBody(); this.setInner(inner); + return this; } @Override - protected ServiceCall createResourceAsync(final ServiceCallback callback) { + public ServiceCall createResourceAsync(final ServiceCallback callback) { + final GenericResourceImpl self = this; return client.createOrUpdateAsync( resourceGroupName(), resourceProviderNamespace, @@ -159,16 +184,17 @@ protected ServiceCall createResourceAsync(final ServiceCallback callback) key(), apiVersion, inner(), - Utils.fromVoidCallback(this, callback)); - } - - @Override - public GenericResourceImpl apply() throws Exception { - return create(); - } - - @Override - public ServiceCall applyAsync(ServiceCallback callback) { - return createAsync(callback); + new ServiceCallback() { + @Override + public void failure(Throwable t) { + callback.failure(t); + } + + @Override + public void success(ServiceResponse response) { + self.setInner(response.getBody()); + callback.success(new ServiceResponse(self, response.getResponse())); + } + }); } } diff --git a/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/implementation/ResourceGroupImpl.java b/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/implementation/ResourceGroupImpl.java index b735906da4b6..7bfd5a597dea 100644 --- a/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/implementation/ResourceGroupImpl.java +++ b/azure-mgmt-resources/src/main/java/com/microsoft/azure/management/resources/implementation/ResourceGroupImpl.java @@ -12,10 +12,11 @@ import com.microsoft.azure.management.resources.ResourceGroupExportResult; import com.microsoft.azure.management.resources.ResourceGroupExportTemplateOptions; import com.microsoft.azure.management.resources.fluentcore.arm.Region; +import com.microsoft.azure.management.resources.fluentcore.arm.models.Resource; import com.microsoft.azure.management.resources.fluentcore.model.implementation.CreatableUpdatableImpl; -import com.microsoft.azure.management.resources.fluentcore.utils.Utils; import com.microsoft.rest.ServiceCall; import com.microsoft.rest.ServiceCallback; +import com.microsoft.rest.ServiceResponse; import java.io.IOException; import java.util.Arrays; @@ -27,7 +28,7 @@ * The implementation for {@link ResourceGroup} and its create and update interfaces. */ class ResourceGroupImpl extends - CreatableUpdatableImpl + CreatableUpdatableImpl implements ResourceGroup, ResourceGroup.DefinitionBlank, @@ -142,18 +143,32 @@ public T connectToResource(ResourceConnector.Build } @Override - protected void createResource() throws Exception { + public Resource createResource() throws Exception { ResourceGroupInner params = new ResourceGroupInner(); params.withLocation(this.inner().location()); params.withTags(this.inner().tags()); - client.createOrUpdate(this.name(), params); + ServiceResponse response = client.createOrUpdate(this.name(), params); + this.setInner(response.getBody()); + return this; } @Override - protected ServiceCall createResourceAsync(final ServiceCallback callback) { + public ServiceCall createResourceAsync(final ServiceCallback callback) { + final ResourceGroupImpl self = this; ResourceGroupInner params = new ResourceGroupInner(); params.withLocation(this.inner().location()); params.withTags(this.inner().tags()); - return client.createOrUpdateAsync(this.name(), params, Utils.fromVoidCallback(this, callback)); + return client.createOrUpdateAsync(this.name(), params, new ServiceCallback() { + @Override + public void failure(Throwable t) { + callback.failure(t); + } + + @Override + public void success(ServiceResponse response) { + self.setInner(response.getBody()); + callback.success(new ServiceResponse(self, response.getResponse())); + } + }); } } diff --git a/azure-mgmt-storage/src/main/java/com/microsoft/azure/management/storage/implementation/StorageAccountImpl.java b/azure-mgmt-storage/src/main/java/com/microsoft/azure/management/storage/implementation/StorageAccountImpl.java index 4c940ee56da3..f15ca28e4072 100644 --- a/azure-mgmt-storage/src/main/java/com/microsoft/azure/management/storage/implementation/StorageAccountImpl.java +++ b/azure-mgmt-storage/src/main/java/com/microsoft/azure/management/storage/implementation/StorageAccountImpl.java @@ -7,8 +7,8 @@ package com.microsoft.azure.management.storage.implementation; import com.microsoft.azure.CloudException; +import com.microsoft.azure.management.resources.fluentcore.arm.models.Resource; import com.microsoft.azure.management.resources.fluentcore.arm.models.implementation.GroupableResourceImpl; -import com.microsoft.azure.management.resources.fluentcore.utils.Utils; import com.microsoft.azure.management.storage.PublicEndpoints; import com.microsoft.azure.management.storage.StorageAccount; import com.microsoft.azure.management.storage.AccessTier; @@ -194,40 +194,6 @@ private void clearWrapperProperties() { publicEndpoints = null; } - @Override - protected void createResource() throws Exception { - createParameters.withLocation(this.regionName()); - createParameters.withTags(this.inner().getTags()); - this.client.create(this.resourceGroupName(), this.name(), createParameters); - // create response does not seems including the endpoints so fetching it again. - StorageAccountInner storageAccountInner = this.client - .getProperties(this.resourceGroupName(), this.name()) - .getBody(); - this.setInner(storageAccountInner); - clearWrapperProperties(); - } - - @Override - protected ServiceCall createResourceAsync(final ServiceCallback callback) { - createParameters.withLocation(this.regionName()); - createParameters.withTags(this.inner().getTags()); - final StorageAccountImpl self = this; - return this.client.createAsync(this.resourceGroupName(), this.name(), createParameters, - new ServiceCallback() { - @Override - public void failure(Throwable t) { - callback.failure(t); - } - - @Override - public void success(ServiceResponse result) { - client.getPropertiesAsync(resourceGroupName(), name(), - Utils.fromVoidCallback(self, callback)); - clearWrapperProperties(); - } - }); - } - @Override public StorageAccountImpl update() { updateParameters = new StorageAccountUpdateParametersInner(); @@ -294,4 +260,52 @@ public StorageAccountImpl withAccessTier(AccessTier accessTier) { } return this; } + + // CreatorTaskGroup.ResourceCreator implementation + + @Override + public Resource createResource() throws Exception { + createParameters.withLocation(this.regionName()); + createParameters.withTags(this.inner().getTags()); + this.client.create(this.resourceGroupName(), this.name(), createParameters); + // create response does not seems including the endpoints so fetching it again. + StorageAccountInner storageAccountInner = this.client + .getProperties(this.resourceGroupName(), this.name()) + .getBody(); + this.setInner(storageAccountInner); + clearWrapperProperties(); + return this; + } + + @Override + public ServiceCall createResourceAsync(final ServiceCallback callback) { + final StorageAccountImpl self = this; + createParameters.withLocation(this.regionName()); + createParameters.withTags(this.inner().getTags()); + return this.client.createAsync(this.resourceGroupName(), this.name(), createParameters, + new ServiceCallback() { + @Override + public void failure(Throwable t) { + callback.failure(t); + } + + @Override + public void success(ServiceResponse result) { + client.getPropertiesAsync(resourceGroupName(), name(), + new ServiceCallback() { + @Override + public void failure(Throwable t) { + callback.failure(t); + } + + @Override + public void success(ServiceResponse response) { + self.setInner(response.getBody()); + clearWrapperProperties(); + callback.success(new ServiceResponse(self, response.getResponse())); + } + }); + } + }); + } } diff --git a/runtimes/azure-client-runtime/src/main/java/com/microsoft/azure/DAGNode.java b/runtimes/azure-client-runtime/src/main/java/com/microsoft/azure/DAGNode.java index 112130413fd8..4e1848fd8c15 100644 --- a/runtimes/azure-client-runtime/src/main/java/com/microsoft/azure/DAGNode.java +++ b/runtimes/azure-client-runtime/src/main/java/com/microsoft/azure/DAGNode.java @@ -10,6 +10,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.concurrent.locks.ReentrantLock; /** * The type representing node in a {@link DAGraph}. @@ -20,6 +21,7 @@ public class DAGNode extends Node { private List dependentKeys; private int toBeResolved; private boolean isPreparer; + private ReentrantLock lock; /** * Creates a DAG node. @@ -30,6 +32,14 @@ public class DAGNode extends Node { public DAGNode(String key, T data) { super(key, data); dependentKeys = new ArrayList<>(); + lock = new ReentrantLock(); + } + + /** + * @return the lock to be used while performing thread safe operation on this node. + */ + public ReentrantLock lock() { + return this.lock; } /** diff --git a/runtimes/azure-client-runtime/src/main/java/com/microsoft/azure/DAGraph.java b/runtimes/azure-client-runtime/src/main/java/com/microsoft/azure/DAGraph.java index 58179e0152ed..153c38f2592a 100644 --- a/runtimes/azure-client-runtime/src/main/java/com/microsoft/azure/DAGraph.java +++ b/runtimes/azure-client-runtime/src/main/java/com/microsoft/azure/DAGraph.java @@ -7,9 +7,8 @@ package com.microsoft.azure; -import java.util.ArrayDeque; import java.util.Map; -import java.util.Queue; +import java.util.concurrent.ConcurrentLinkedQueue; /** * Type representing a DAG (directed acyclic graph). @@ -20,7 +19,7 @@ * @param the type of the nodes in the graph */ public class DAGraph> extends Graph { - private Queue queue; + private ConcurrentLinkedQueue queue; private boolean hasParent; private U rootNode; @@ -31,7 +30,7 @@ public class DAGraph> extends Graph { */ public DAGraph(U rootNode) { this.rootNode = rootNode; - this.queue = new ArrayDeque<>(); + this.queue = new ConcurrentLinkedQueue<>(); this.rootNode.setPreparer(true); this.addNode(rootNode); } @@ -103,10 +102,14 @@ public void prepare() { * Gets next node in the DAG which has no dependency or all of it's dependencies are resolved and * ready to be consumed. * - * @return next node or null if all the nodes have been explored + * @return next node or null if all the nodes have been explored or no node is available at this moment. */ public U getNext() { - return graph.get(queue.poll()); + String nextItemKey = queue.poll(); + if (nextItemKey == null) { + return null; + } + return graph.get(nextItemKey); } /** @@ -129,9 +132,14 @@ public void reportedCompleted(U completed) { String dependency = completed.key(); for (String dependentKey : graph.get(dependency).dependentKeys()) { DAGNode dependent = graph.get(dependentKey); - dependent.reportResolved(dependency); - if (dependent.hasAllResolved()) { - queue.add(dependent.key()); + dependent.lock().lock(); + try { + dependent.reportResolved(dependency); + if (dependent.hasAllResolved()) { + queue.add(dependent.key()); + } + } finally { + dependent.lock().unlock(); } } } @@ -145,9 +153,8 @@ public void reportedCompleted(U completed) { */ private void initializeDependentKeys() { visit(new Visitor() { - // This 'visit' will be called only once per each node. @Override - public void visit(U node) { + public void visitNode(U node) { if (node.dependencyKeys().isEmpty()) { return; } @@ -158,6 +165,13 @@ public void visit(U node) { .addDependent(dependentKey); } } + + @Override + public void visitEdge(String fromKey, String toKey, EdgeType edgeType) { + if (edgeType == EdgeType.BACK) { + throw new IllegalStateException("Detected circular dependency: " + findPath(fromKey, toKey)); + } + } }); } diff --git a/runtimes/azure-client-runtime/src/main/java/com/microsoft/azure/Graph.java b/runtimes/azure-client-runtime/src/main/java/com/microsoft/azure/Graph.java index 40ceebaa50b2..89087dd6d358 100644 --- a/runtimes/azure-client-runtime/src/main/java/com/microsoft/azure/Graph.java +++ b/runtimes/azure-client-runtime/src/main/java/com/microsoft/azure/Graph.java @@ -23,6 +23,11 @@ public class Graph> { protected Map graph; private Set visited; + private Integer time; + private Map entryTime; + private Map exitTime; + private Map parent; + private Set processed; /** * Creates a directed graph. @@ -30,6 +35,11 @@ public class Graph> { public Graph() { this.graph = new HashMap<>(); this.visited = new HashSet<>(); + this.time = 0; + this.entryTime = new HashMap<>(); + this.exitTime = new HashMap<>(); + this.parent = new HashMap<>(); + this.processed = new HashSet<>(); } /** @@ -41,26 +51,11 @@ public void addNode(U node) { graph.put(node.key(), node); } - /** - * Represents a visitor to be implemented by the consumer who want to visit the - * graph's nodes in DFS order. - * - * @param the type of the node - */ - interface Visitor { - /** - * visit a node. - * - * @param node the node to visited - */ - void visit(U node); - } - /** * Perform DFS visit in this graph. *

* The directed graph will be traversed in DFS order and the visitor will be notified as - * search explores each node + * search explores each node and edge. * * @param visitor the graph visitor */ @@ -71,15 +66,107 @@ public void visit(Visitor visitor) { } } visited.clear(); + time = 0; + entryTime.clear(); + exitTime.clear(); + parent.clear(); + processed.clear(); } private void dfs(Visitor visitor, Node node) { - visitor.visit(node); - visited.add(node.key()); - for (String childKey : node.children()) { - if (!visited.contains(childKey)) { - this.dfs(visitor, this.graph.get(childKey)); + visitor.visitNode(node); + + String fromKey = node.key(); + visited.add(fromKey); + time++; + entryTime.put(fromKey, time); + for (String toKey : node.children()) { + if (!visited.contains(toKey)) { + parent.put(toKey, fromKey); + visitor.visitEdge(fromKey, toKey, edgeType(fromKey, toKey)); + this.dfs(visitor, this.graph.get(toKey)); + } else { + visitor.visitEdge(fromKey, toKey, edgeType(fromKey, toKey)); } } + time++; + exitTime.put(fromKey, time); + processed.add(fromKey); + } + + private EdgeType edgeType(String fromKey, String toKey) { + if (parent.containsKey(toKey) && parent.get(toKey).equals(fromKey)) { + return EdgeType.TREE; + } + + if (visited.contains(toKey) && !processed.contains(toKey)) { + return EdgeType.BACK; + } + + if (processed.contains(toKey) && entryTime.containsKey(toKey) && entryTime.containsKey(fromKey)) { + if (entryTime.get(toKey) > entryTime.get(fromKey)) { + return EdgeType.FORWARD; + } + + if (entryTime.get(toKey) < entryTime.get(fromKey)) { + return EdgeType.CROSS; + } + } + + throw new IllegalStateException("Internal Error: Unable to locate the edge type {" + fromKey + ", " + toKey + "}"); + } + + protected String findPath(String start, String end) { + if (start.equals(end)) { + return start; + } else { + return findPath(start, parent.get(end)) + " -> " + end; + } + } + + /** + * The edge types in a graph. + */ + enum EdgeType { + /** + * An edge (u, v) is a tree edge if v is visited the first time. + */ + TREE, + /** + * An edge (u, v) is a forward edge if v is descendant of u. + */ + FORWARD, + /** + * An edge (u, v) is a back edge if v is ancestor of u. + */ + BACK, + /** + * An edge (u, v) is a cross edge if v is neither ancestor or descendant of u. + */ + CROSS + } + + /** + * Represents a visitor to be implemented by the consumer who want to visit the + * graph's nodes in DFS order by calling visit method. + * + * @param the type of the node + */ + interface Visitor { + /** + * visit a node. + * + * @param node the node to visited + */ + void visitNode(U node); + + /** + * visit an edge. + * + * @param fromKey key of the from node + * @param toKey key of the to node + * @param edgeType the edge type + */ + void visitEdge(String fromKey, String toKey, EdgeType edgeType); } } diff --git a/runtimes/azure-client-runtime/src/main/java/com/microsoft/azure/TaskGroup.java b/runtimes/azure-client-runtime/src/main/java/com/microsoft/azure/TaskGroup.java index 26bbbece2606..3ad514d93874 100644 --- a/runtimes/azure-client-runtime/src/main/java/com/microsoft/azure/TaskGroup.java +++ b/runtimes/azure-client-runtime/src/main/java/com/microsoft/azure/TaskGroup.java @@ -63,7 +63,7 @@ public interface TaskGroup> { * @param callback the callback to call on failure or success * @return the handle to the REST call */ - ServiceCall executeAsync(ServiceCallback callback); + ServiceCall executeAsync(ServiceCallback callback); /** * Gets the result of execution of a task in the group. diff --git a/runtimes/azure-client-runtime/src/main/java/com/microsoft/azure/TaskGroupBase.java b/runtimes/azure-client-runtime/src/main/java/com/microsoft/azure/TaskGroupBase.java index efc8d30e491b..b607a41f54ad 100644 --- a/runtimes/azure-client-runtime/src/main/java/com/microsoft/azure/TaskGroupBase.java +++ b/runtimes/azure-client-runtime/src/main/java/com/microsoft/azure/TaskGroupBase.java @@ -9,6 +9,9 @@ import com.microsoft.rest.ServiceCall; import com.microsoft.rest.ServiceCallback; +import com.microsoft.rest.ServiceResponse; + +import java.util.concurrent.ConcurrentLinkedQueue; /** * The base implementation of TaskGroup interface. @@ -18,6 +21,7 @@ public abstract class TaskGroupBase implements TaskGroup> { private DAGraph, DAGNode>> dag; + private ParallelServiceCall parallelServiceCall; /** * Creates TaskGroupBase. @@ -27,6 +31,7 @@ public abstract class TaskGroupBase */ public TaskGroupBase(String rootTaskItemId, TaskItem rootTaskItem) { this.dag = new DAGraph<>(new DAGNode<>(rootTaskItemId, rootTaskItem)); + this.parallelServiceCall = new ParallelServiceCall(); } @Override @@ -54,29 +59,17 @@ public void prepare() { @Override public void execute() throws Exception { DAGNode> nextNode = dag.getNext(); - if (nextNode == null) { - return; - } - - if (dag.isRootNode(nextNode)) { - executeRootTask(nextNode.data()); - } else { - nextNode.data().execute(this, nextNode); + while (nextNode != null) { + nextNode.data().execute(); + this.dag().reportedCompleted(nextNode); + nextNode = dag.getNext(); } } @Override - public ServiceCall executeAsync(final ServiceCallback callback) { - final DAGNode> nextNode = dag.getNext(); - if (nextNode == null) { - return null; - } - - if (dag.isRootNode(nextNode)) { - return executeRootTaskAsync(nextNode.data(), callback); - } else { - return nextNode.data().executeAsync(this, nextNode, callback); - } + public ServiceCall executeAsync(final ServiceCallback callback) { + executeReadyTasksAsync(callback); + return parallelServiceCall; } @Override @@ -85,27 +78,90 @@ public T taskResult(String taskId) { } /** - * Executes the root task in this group. - *

- * This method will be invoked when all the task dependencies of the root task are finished - * executing, at this point root task can be executed by consuming the result of tasks it - * depends on. + * Executes all runnable tasks, a task is runnable when all the tasks its depends + * on are finished running. * - * @param task the root task in this group - * @throws Exception the exception + * @param callback the callback */ - public abstract void executeRootTask(TaskItem task) throws Exception; + private void executeReadyTasksAsync(final ServiceCallback callback) { + DAGNode> nextNode = dag.getNext(); + while (nextNode != null) { + ServiceCall serviceCall = nextNode.data().executeAsync(taskCallback(nextNode, callback)); + this.parallelServiceCall.addCall(serviceCall); + nextNode = dag.getNext(); + } + } /** - * Executes the root task in this group asynchronously. - *

- * This method will be invoked when all the task dependencies of the root task are finished - * executing, at this point root task can be executed by consuming the result of tasks it - * depends on. + * This method create and return a callback for the runnable task stored in the given node. + * This callback wraps the given callback. * - * @param task the root task in this group - * @param callback the callback when the task fails or succeeds - * @return the handle to the REST call + * @param taskNode the node containing runnable task + * @param callback the callback to wrap + * @return the task callback */ - public abstract ServiceCall executeRootTaskAsync(TaskItem task, ServiceCallback callback); + private ServiceCallback taskCallback(final DAGNode> taskNode, final ServiceCallback callback) { + final TaskGroupBase self = this; + return new ServiceCallback() { + @Override + public void failure(Throwable t) { + callback.failure(t); + } + + @Override + public void success(ServiceResponse result) { + self.dag().reportedCompleted(taskNode); + if (self.dag().isRootNode(taskNode)) { + callback.success(result); + } else { + self.executeReadyTasksAsync(callback); + } + } + }; + } + + /** + * Type represents a set of REST calls running possibly in parallel. + */ + private class ParallelServiceCall extends ServiceCall { + private ConcurrentLinkedQueue serviceCalls; + + /** + * Creates a ParallelServiceCall. + */ + ParallelServiceCall() { + super(null); + this.serviceCalls = new ConcurrentLinkedQueue<>(); + } + + /** + * Cancels all the service calls currently executing. + */ + public void cancel() { + for (ServiceCall call : this.serviceCalls) { + call.cancel(); + } + } + + /** + * @return true if the call has been canceled; false otherwise. + */ + public boolean isCancelled() { + for (ServiceCall call : this.serviceCalls) { + if (!call.isCanceled()) { + return false; + } + } + return true; + } + + /** + * Add a call to the list of parallel calls. + * + * @param call the call + */ + private void addCall(ServiceCall call) { + this.serviceCalls.add(call); + } + } } diff --git a/runtimes/azure-client-runtime/src/main/java/com/microsoft/azure/TaskItem.java b/runtimes/azure-client-runtime/src/main/java/com/microsoft/azure/TaskItem.java index fb74c23845c3..8f0a3459a2e9 100644 --- a/runtimes/azure-client-runtime/src/main/java/com/microsoft/azure/TaskItem.java +++ b/runtimes/azure-client-runtime/src/main/java/com/microsoft/azure/TaskItem.java @@ -26,21 +26,17 @@ public interface TaskItem { *

* once executed the result will be available through result getter * - * @param taskGroup the task group dispatching tasks - * @param node the node the task item is associated with * @throws Exception exception */ - void execute(TaskGroup> taskGroup, DAGNode> node) throws Exception; + void execute() throws Exception; /** * Executes the task asynchronously. *

* once executed the result will be available through result getter - - * @param taskGroup the task group dispatching tasks - * @param node the node the task item is associated with + * * @param callback callback to call on success or failure * @return the handle of the REST call */ - ServiceCall executeAsync(TaskGroup> taskGroup, DAGNode> node, ServiceCallback callback); + ServiceCall executeAsync(ServiceCallback callback); }