diff --git a/.gitignore b/.gitignore
index 565e7ae9fb..b796b11f6e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -289,4 +289,7 @@ __pycache__/
package-lock.json
*.class
-test/*/target/
\ No newline at end of file
+test/*/target/
+.settings/
+.project
+.classpath
\ No newline at end of file
diff --git a/src/azure/Model/CodeModelJva.cs b/src/azure/Model/CodeModelJva.cs
index c21b0169cf..63d5c99031 100644
--- a/src/azure/Model/CodeModelJva.cs
+++ b/src/azure/Model/CodeModelJva.cs
@@ -1,4 +1,4 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
+// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
using System.Collections.Generic;
@@ -8,6 +8,8 @@
using AutoRest.Java.Model;
using AutoRest.Core.Utilities.Collections;
using Newtonsoft.Json;
+using System.Text.RegularExpressions;
+using AutoRest.Core;
namespace AutoRest.Java.Azure.Model
{
@@ -64,5 +66,61 @@ public string SetDefaultHeaders
return "";
}
}
+
+ ///
+ /// Attempts to infer the name of the service referenced by this CodeModel.
+ ///
+ [JsonIgnore]
+ public string ServiceName
+ {
+ get
+ {
+ var serviceNameSetting = Settings.Instance.Host?.GetValue("service-name").Result;
+ if (!string.IsNullOrEmpty(serviceNameSetting))
+ {
+ return serviceNameSetting;
+ }
+
+ var method = Methods[0];
+ var match = Regex.Match(input: method.Url, pattern: @"/providers/microsoft\.(\w+)/", options: RegexOptions.IgnoreCase);
+ var serviceName = match.Groups[1].Value.ToPascalCase();
+ return serviceName;
+ }
+ }
+
+
+ const string targetVersion = "1.1.3";
+ ///
+ /// The Azure SDK version to reference in the generated POM.
+ ///
+ [JsonIgnore]
+ public string PomVersion
+ {
+ get
+ {
+ return targetVersion + "-SNAPSHOT";
+ }
+ }
+
+ ///
+ /// The Beta.SinceVersion value to pass to the Beta annotation.
+ ///
+ [JsonIgnore]
+ public string BetaSinceVersion
+ {
+ get
+ {
+ var versionParts = targetVersion.Split('.');
+ var minorVersion = int.Parse(versionParts[1]);
+ var patchVersion = int.Parse(versionParts[2]);
+
+ var newMinorVersion = patchVersion == 0
+ ? minorVersion
+ : minorVersion + 1;
+
+ var result = "V" + versionParts[0] + "_" + newMinorVersion + "_0";
+ return result;
+ }
+ }
}
-}
\ No newline at end of file
+}
diff --git a/src/azure/Templates/AzurePomTemplate.cshtml b/src/azure/Templates/AzurePomTemplate.cshtml
new file mode 100644
index 0000000000..6ce1102091
--- /dev/null
+++ b/src/azure/Templates/AzurePomTemplate.cshtml
@@ -0,0 +1,136 @@
+@using System
+@using System.Linq;
+@using AutoRest.Java
+@using AutoRest.Java.Model
+@using AutoRest.Java.Azure.Model
+@inherits AutoRest.Core.Template
+@{
+ var serviceName = Model.ServiceName;
+}
+
+
+ 4.0.0
+
+ com.microsoft.azure
+ azure-parent
+ @Model.PomVersion
+ ../pom.xml
+
+
+ azure-mgmt-@serviceName.ToLower()
+ jar
+
+ Microsoft Azure SDK for @serviceName Management
+ This package contains Microsoft @serviceName Management SDK.
+ https://github.com/Azure/azure-sdk-for-java
+
+
+
+ The MIT License (MIT)
+ http://opensource.org/licenses/MIT
+ repo
+
+
+
+
+ scm:git:https://github.com/Azure/azure-sdk-for-java
+ scm:git:git@github.com:Azure/azure-sdk-for-java.git
+ HEAD
+
+
+
+ UTF-8
+
+
+
+
+
+ microsoft
+ Microsoft
+
+
+
+
+
+ com.microsoft.azure
+ azure-client-runtime
+
+
+ com.microsoft.azure
+ azure-mgmt-resources
+ @Model.PomVersion
+
+
+ junit
+ junit
+ test
+
+
+ com.microsoft.azure
+ azure-client-authentication
+ test
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+
+
+
+ true
+ true
+
+
+
+
+
+ org.codehaus.mojo
+ build-helper-maven-plugin
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.1
+
+ 1.7
+ 1.7
+
+
+ com.microsoft.azure.management.apigeneration.LangDefinitionProcessor
+
+
+ true
+ true
+
+ true
+ true
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-javadoc-plugin
+ 2.8
+
+ *.implementation.*;*.utils.*;com.microsoft.schemas._2003._10.serialization;*.blob.core.search
+
+
+ /**
+
* Copyright (c) Microsoft Corporation. All rights reserved.
+
* Licensed under the MIT License. See License.txt in the project root for
+
* license information.
+
*/
+ ]]>
+
+
+
+
+
+
+
diff --git a/src/azure/Templates/AzureServiceManagerTemplate.cshtml b/src/azure/Templates/AzureServiceManagerTemplate.cshtml
new file mode 100644
index 0000000000..2e6a85caae
--- /dev/null
+++ b/src/azure/Templates/AzureServiceManagerTemplate.cshtml
@@ -0,0 +1,107 @@
+@using System
+@using System.Text.RegularExpressions
+@using System.Linq
+@using AutoRest.Core.Utilities
+@using AutoRest.Java
+@using AutoRest.Java.Azure.Model
+@using AutoRest.Java.Model
+@inherits AutoRest.Core.Template
+
+@{
+ var serviceName = Model.ServiceName;
+ var className = serviceName + "Manager";
+}
+
+/**
+@Header(" * ").TrimMultilineHeader()
+ */
+@EmptyLine
+
+package @(Settings.Namespace.ToLower()).@(Model.ImplPackage);
+
+@EmptyLine
+import com.microsoft.azure.AzureEnvironment;
+import com.microsoft.azure.AzureResponseBuilder;
+import com.microsoft.azure.credentials.AzureTokenCredentials;
+import com.microsoft.azure.management.apigeneration.Beta;
+import com.microsoft.azure.management.apigeneration.Beta.SinceVersion;
+import com.microsoft.azure.management.resources.fluentcore.arm.AzureConfigurable;
+import com.microsoft.azure.management.resources.fluentcore.arm.implementation.AzureConfigurableImpl;
+import com.microsoft.azure.management.resources.fluentcore.arm.implementation.Manager;
+import com.microsoft.azure.management.resources.fluentcore.utils.ProviderRegistrationInterceptor;
+import com.microsoft.azure.serializer.AzureJacksonAdapter;
+import com.microsoft.rest.RestClient;
+@EmptyLine
+
+/**
+ * Entry point to Azure @(serviceName) resource management.
+ */
+@@Beta(SinceVersion.@Model.BetaSinceVersion)
+public final class @(className) extends Manager<@(className), @(Model.Name + "Impl")> {
+ /**
+ * Get a Configurable instance that can be used to create @(className) with optional configuration.
+ *
+ * @@return the instance allowing configurations
+ */
+ public static Configurable configure() {
+ return new @(className).ConfigurableImpl();
+ }
+
+ /**
+ * Creates an instance of @className that exposes @serviceName resource management API entry points.
+ *
+ * @@param credentials the credentials to use
+ * @@param subscriptionId the subscription UUID
+ * @@return the @className
+ */
+ public static @className authenticate(AzureTokenCredentials credentials, String subscriptionId) {
+ return new @(className)(new RestClient.Builder()
+ .withBaseUrl(credentials.environment(), AzureEnvironment.Endpoint.RESOURCE_MANAGER)
+ .withCredentials(credentials)
+ .withSerializerAdapter(new AzureJacksonAdapter())
+ .withResponseBuilderFactory(new AzureResponseBuilder.Factory())
+ .withInterceptor(new ProviderRegistrationInterceptor(credentials))
+ .build(), subscriptionId);
+ }
+
+ /**
+ * Creates an instance of @className that exposes @serviceName resource management API entry points.
+ *
+ * @@param restClient the RestClient to be used for API calls.
+ * @@param subscriptionId the subscription UUID
+ * @@return the @className
+ */
+ public static @className authenticate(RestClient restClient, String subscriptionId) {
+ return new @(className)(restClient, subscriptionId);
+ }
+
+ /**
+ * The interface allowing configurations to be set.
+ */
+ public interface Configurable extends AzureConfigurable {
+ /**
+ * Creates an instance of @className that exposes @serviceName management API entry points.
+ *
+ * @@param credentials the credentials to use
+ * @@param subscriptionId the subscription UUID
+ * @@return the interface exposing @serviceName management API entry points that work across subscriptions
+ */
+ @className authenticate(AzureTokenCredentials credentials, String subscriptionId);
+ }
+
+ /**
+ * The implementation for Configurable interface.
+ */
+ private static final class ConfigurableImpl extends AzureConfigurableImpl implements Configurable {
+ public @className authenticate(AzureTokenCredentials credentials, String subscriptionId) {
+ return @(className).authenticate(buildRestClient(credentials), subscriptionId);
+ }
+ }
+
+ private @(className)(RestClient restClient, String subscriptionId) {
+ super(
+ restClient,
+ subscriptionId,
+ new @(Model.Name)Impl(restClient).withSubscriptionId(subscriptionId));
+ }
+}
diff --git a/src/azurefluent/CodeGeneratorJvaf.cs b/src/azurefluent/CodeGeneratorJvaf.cs
index 9c218afeef..494ff2e9eb 100644
--- a/src/azurefluent/CodeGeneratorJvaf.cs
+++ b/src/azurefluent/CodeGeneratorJvaf.cs
@@ -16,6 +16,7 @@
using AutoRest.Java.Model;
using AutoRest.Java.vanilla.Templates;
using System;
+using System.Text.RegularExpressions;
namespace AutoRest.Java.Azure.Fluent
{
@@ -35,6 +36,8 @@ public class CodeGeneratorJvaf : CodeGeneratorJva
///
public override async Task Generate(CodeModel cm)
{
+ var packagePath = Path.Combine("src/main/java", cm.Namespace.ToLower().Replace('.', '/'));
+
// get Azure Java specific codeModel
var codeModel = cm as CodeModelJvaf;
if (codeModel == null)
@@ -44,14 +47,14 @@ public override async Task Generate(CodeModel cm)
// Service client
var serviceClientTemplate = new AzureServiceClientTemplate { Model = codeModel };
- await Write(serviceClientTemplate, $"{Path.Combine("implementation", codeModel.Name.ToPascalCase() + "Impl")}{ImplementationFileExtension}");
+ await Write(serviceClientTemplate, Path.Combine(packagePath, "implementation", codeModel.Name.ToPascalCase() + "Impl" + ImplementationFileExtension));
// operations
foreach (MethodGroupJvaf methodGroup in codeModel.AllOperations)
{
// Operation
var operationsTemplate = new AzureMethodGroupTemplate { Model = methodGroup };
- await Write(operationsTemplate, $"{Path.Combine("implementation", methodGroup.TypeName.ToPascalCase())}Inner{ImplementationFileExtension}");
+ await Write(operationsTemplate, Path.Combine(packagePath, "implementation", methodGroup.TypeName.ToPascalCase()) + "Inner" + ImplementationFileExtension);
}
//Models
@@ -68,14 +71,14 @@ public override async Task Generate(CodeModel cm)
}
var modelTemplate = new ModelTemplate { Model = modelType };
- await Write(modelTemplate, Path.Combine(modelType.ModelsPackage.Trim('.'), $"{modelType.Name.ToPascalCase()}{ImplementationFileExtension}"));
+ await Write(modelTemplate, Path.Combine(packagePath, modelType.ModelsPackage.Trim('.'), $"{modelType.Name.ToPascalCase()}{ImplementationFileExtension}"));
}
//Enums
foreach (EnumTypeJvaf enumType in cm.EnumTypes)
{
var enumTemplate = new EnumTemplate { Model = enumType };
- await Write(enumTemplate, Path.Combine(enumType.ModelsPackage.Trim('.'), $"{enumTemplate.Model.Name.ToPascalCase()}{ImplementationFileExtension}"));
+ await Write(enumTemplate, Path.Combine(packagePath, enumType.ModelsPackage.Trim('.'), $"{enumTemplate.Model.Name.ToPascalCase()}{ImplementationFileExtension}"));
}
// Page class
@@ -85,7 +88,7 @@ public override async Task Generate(CodeModel cm)
{
Model = new PageJvaf(pageClass.Value, pageClass.Key.Key, pageClass.Key.Value),
};
- await Write(pageTemplate, Path.Combine("implementation", $"{pageTemplate.Model.TypeDefinitionName.ToPascalCase()}{ImplementationFileExtension}"));
+ await Write(pageTemplate, Path.Combine(packagePath, "implementation", $"{pageTemplate.Model.TypeDefinitionName.ToPascalCase()}{ImplementationFileExtension}"));
}
// Exceptions
@@ -97,18 +100,29 @@ public override async Task Generate(CodeModel cm)
}
var exceptionTemplate = new ExceptionTemplate { Model = exceptionType };
- await Write(exceptionTemplate, Path.Combine(exceptionType.ModelsPackage.Trim('.'), $"{exceptionTemplate.Model.ExceptionTypeDefinitionName}{ImplementationFileExtension}"));
+ await Write(exceptionTemplate, Path.Combine(packagePath, exceptionType.ModelsPackage.Trim('.'), $"{exceptionTemplate.Model.ExceptionTypeDefinitionName}{ImplementationFileExtension}"));
}
// package-info.java
await Write(new PackageInfoTemplate
{
Model = new PackageInfoTemplateModel(cm)
- }, _packageInfoFileName);
+ }, Path.Combine(packagePath, _packageInfoFileName));
await Write(new PackageInfoTemplate
{
Model = new PackageInfoTemplateModel(cm, "implementation")
- }, Path.Combine("implementation", _packageInfoFileName));
+ }, Path.Combine(packagePath, "implementation", _packageInfoFileName));
+
+ if (true == AutoRest.Core.Settings.Instance.Host?.GetValue("regenerate-manager").Result)
+ {
+ // Manager
+ await Write(
+ new AzureServiceManagerTemplate { Model = codeModel },
+ Path.Combine(packagePath, "implementation", codeModel.ServiceName + "Manager" + ImplementationFileExtension));
+
+ // POM
+ await Write(new AzurePomTemplate { Model = codeModel }, "pom.xml");
+ }
}
}
}
diff --git a/src/azurefluent/Model/MethodJvaf.cs b/src/azurefluent/Model/MethodJvaf.cs
index db6ea8d569..88da06a653 100644
--- a/src/azurefluent/Model/MethodJvaf.cs
+++ b/src/azurefluent/Model/MethodJvaf.cs
@@ -1,4 +1,4 @@
-// Copyright (c) Microsoft Corporation. All rights reserved.
+// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.
using System.Collections.Generic;
@@ -223,6 +223,21 @@ private enum MethodType
Delete
}
+ private static bool HasSequenceType(IModelType mt)
+ {
+ if (mt is SequenceType)
+ {
+ return true;
+ }
+
+ if (mt is CompositeType ct)
+ {
+ return ct.Properties.Any(p => HasSequenceType(p.ModelType));
+ }
+
+ return false;
+ }
+
private static MethodType GetMethodType(MethodJvaf method)
{
Regex leading = new Regex("^/+");
@@ -233,7 +248,7 @@ private static MethodType GetMethodType(MethodJvaf method)
var urlSplits = methodUrl.Split('/');
if ((urlSplits.Count() == 5 || urlSplits.Count() == 7)
&& StringComparer.OrdinalIgnoreCase.Equals(urlSplits[0], "subscriptions")
- && method.ReturnType.Body is SequenceType)
+ && HasSequenceType(method.ReturnType.Body))
{
if (urlSplits.Count() == 5)
{