Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.openapitools.codegen.languages.PowerShellClientCodegen Maven / Gradle / Ivy
/*
* Copyright 2018 OpenAPI-Generator Contributors (https://openapi-generator.tech)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.openapitools.codegen.languages;
import io.swagger.v3.oas.models.media.ArraySchema;
import io.swagger.v3.oas.models.media.Schema;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils;
import org.openapitools.codegen.*;
import org.openapitools.codegen.meta.GeneratorMetadata;
import org.openapitools.codegen.meta.Stability;
import org.openapitools.codegen.meta.features.*;
import org.openapitools.codegen.utils.ModelUtils;
import org.openapitools.codegen.utils.ProcessUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.util.*;
import static java.util.UUID.randomUUID;
import static org.openapitools.codegen.utils.StringUtils.camelize;
public class PowerShellClientCodegen extends DefaultCodegen implements CodegenConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(PowerShellClientCodegen.class);
private String packageGuid = "{" + randomUUID().toString().toUpperCase(Locale.ROOT) + "}";
protected String sourceFolder = "src";
protected String packageName = "PSOpenAPITools";
protected String packageVersion = "0.1.2";
protected String apiDocPath = "docs/";
protected String modelDocPath = "docs/";
protected String apiTestPath = "tests/Api";
protected String modelTestPath = "tests/Model";
protected HashSet nullablePrimitives;
protected String powershellGalleryUrl;
protected HashSet powershellVerbs;
protected Map commonVerbs; // verbs not in the official ps verb list but can be mapped to one of the verbs
protected HashSet methodNames; // store a list of method names to detect duplicates
protected boolean useOneOfDiscriminatorLookup = false; // use oneOf discriminator's mapping for model lookup
protected boolean discardReadOnly = false; // Discard the readonly property in initialize cmdlet
protected boolean skipVerbParsing = false; // Attempt to parse cmdlets from operation names
protected String projectUri;
protected String licenseUri;
protected String releaseNotes;
protected String tags;
protected String iconUri;
/**
* Constructs an instance of `PowerShellClientCodegen`.
*/
public PowerShellClientCodegen() {
super();
modifyFeatureSet(features -> features
.includeDocumentationFeatures(DocumentationFeature.Readme)
.wireFormatFeatures(EnumSet.of(WireFormatFeature.JSON, WireFormatFeature.XML))
.securityFeatures(EnumSet.of(
SecurityFeature.BasicAuth,
SecurityFeature.ApiKey,
SecurityFeature.OAuth2_Implicit
))
.excludeGlobalFeatures(
GlobalFeature.XMLStructureDefinitions,
GlobalFeature.Callbacks,
GlobalFeature.LinkObjects,
GlobalFeature.ParameterStyling
)
.excludeSchemaSupportFeatures(
SchemaSupportFeature.Polymorphism
)
.excludeParameterFeatures(
ParameterFeature.Cookie
)
);
generatorMetadata = GeneratorMetadata.newBuilder(generatorMetadata)
.stability(Stability.BETA)
.build();
outputFolder = "generated-code" + File.separator + "powershell-expiermental";
modelTemplateFiles.put("model.mustache", ".ps1");
apiTemplateFiles.put("api.mustache", ".ps1");
modelTestTemplateFiles.put("model_test.mustache", ".ps1");
apiTestTemplateFiles.put("api_test.mustache", ".ps1");
modelDocTemplateFiles.put("model_doc.mustache", ".md");
apiDocTemplateFiles.put("api_doc.mustache", ".md");
embeddedTemplateDir = templateDir = "powershell";
apiPackage = packageName + File.separator + "Api";
modelPackage = packageName + File.separator + "Model";
// https://blogs.msdn.microsoft.com/powershell/2010/01/07/how-objects-are-sent-to-and-from-remote-sessions/
languageSpecificPrimitives = new HashSet(Arrays.asList(
"Byte",
"SByte",
"Byte[]",
"Int16",
"Int32",
"Int64",
"UInt16",
"UInt32",
"UInt64",
"Decimal",
"Single",
"Double",
"TimeSpan",
"System.DateTime",
"ProgressRecord",
"Char",
"String",
"XmlDocument",
"SecureString",
"Boolean",
"Guid",
"Uri",
"System.IO.FileInfo",
"Version"
));
commonVerbs = new HashMap();
Map> verbMappings = new HashMap>();
// common
verbMappings.put("Add", Arrays.asList("Append", "Attach", "Concatenate", "Insert"));
verbMappings.put("Clear", Arrays.asList("Flush", "Erase", "Release", "Unmark", "Unset", "Nullify"));
verbMappings.put("Close", Arrays.asList());
verbMappings.put("Copy", Arrays.asList("Duplicate", "Clone", "Replicate", "Sync"));
verbMappings.put("Enter", Arrays.asList("PushInto"));
verbMappings.put("Exit", Arrays.asList("PopOut"));
verbMappings.put("Find", Arrays.asList());
verbMappings.put("Format", Arrays.asList());
verbMappings.put("Get", Arrays.asList("Read", "Open", "Cat", "Type", "Dir", "Obtain", "Dump", "Acquire", "Examine", "Find", "Search"));
verbMappings.put("Hide", Arrays.asList("Block"));
verbMappings.put("Join", Arrays.asList("Combine", "Unite", "Connect", "Associate"));
verbMappings.put("Lock", Arrays.asList("RestrictSecure"));
verbMappings.put("Move", Arrays.asList("Transfer", "Name", "Migrate"));
verbMappings.put("New", Arrays.asList("Create", "Generate", "Build", "Make", "Allocate"));
verbMappings.put("Open", Arrays.asList());
verbMappings.put("Optimize", Arrays.asList());
verbMappings.put("Pop", Arrays.asList());
verbMappings.put("Push", Arrays.asList());
verbMappings.put("Redo", Arrays.asList());
verbMappings.put("Remove", Arrays.asList("Clear", "Cut", "Dispose", "Discard", "Erase"));
verbMappings.put("Rename", Arrays.asList("Change"));
verbMappings.put("Reset", Arrays.asList());
verbMappings.put("Search", Arrays.asList("FindLocate"));
verbMappings.put("Select", Arrays.asList("FindLocate"));
verbMappings.put("Set", Arrays.asList("Write", "Reset", "Assign", "Configure"));
verbMappings.put("Show", Arrays.asList("DisplayProduce"));
verbMappings.put("Skip", Arrays.asList("BypassJump"));
verbMappings.put("Split", Arrays.asList("parate"));
verbMappings.put("Step", Arrays.asList());
verbMappings.put("Switch", Arrays.asList());
verbMappings.put("Undo", Arrays.asList());
verbMappings.put("Unlock", Arrays.asList("Release", "Unrestrict", "Unsecure"));
verbMappings.put("Watch", Arrays.asList());
// communication
verbMappings.put("Connect", Arrays.asList("JoinTelnet"));
verbMappings.put("Disconnect", Arrays.asList("BreakLogoff"));
verbMappings.put("Read", Arrays.asList("Acquire", "Prompt", "Get"));
verbMappings.put("Receive", Arrays.asList("Read", "Accept", "Peek"));
verbMappings.put("Send", Arrays.asList("Put", "Broadcast", "Mail", "Fax"));
verbMappings.put("Write", Arrays.asList("PutPrint"));
// data
verbMappings.put("Backup", Arrays.asList(" Save", " Burn", " Replicate", "Sync"));
verbMappings.put("Checkpoint", Arrays.asList(" Diff"));
verbMappings.put("Compare", Arrays.asList(" Diff"));
verbMappings.put("Compress", Arrays.asList(" Compact"));
verbMappings.put("Convert", Arrays.asList(" Change", " Resize", "Resample"));
verbMappings.put("ConvertFrom", Arrays.asList(" Export", " Output", "Out"));
verbMappings.put("ConvertTo", Arrays.asList(" Import", " Input", "In"));
verbMappings.put("Dismount", Arrays.asList(" UnmountUnlink"));
verbMappings.put("Edit", Arrays.asList(" Change", " Update", "Modify"));
verbMappings.put("Expand", Arrays.asList(" ExplodeUncompress"));
verbMappings.put("Export", Arrays.asList(" ExtractBackup"));
verbMappings.put("Group", Arrays.asList(" Aggregate", " Arrange", " Associate", "Correlate"));
verbMappings.put("Import", Arrays.asList(" BulkLoadLoad"));
verbMappings.put("Initialize", Arrays.asList(" Erase", " Init", " Renew", " Rebuild", " Reinitialize", "Setup"));
verbMappings.put("Limit", Arrays.asList(" Quota"));
verbMappings.put("Merge", Arrays.asList(" CombineJoin"));
verbMappings.put("Mount", Arrays.asList(" Connect"));
verbMappings.put("Out", Arrays.asList());
verbMappings.put("Publish", Arrays.asList(" Deploy", " Release", "Install"));
verbMappings.put("Restore", Arrays.asList(" Repair", " Return", " Undo", "Fix"));
verbMappings.put("Save", Arrays.asList());
verbMappings.put("Sync", Arrays.asList(" Replicate", " Coerce", "Match"));
verbMappings.put("Unpublish", Arrays.asList(" Uninstall", " Revert", "Hide"));
verbMappings.put("Update", Arrays.asList(" Refresh", " Renew", " Recalculate", "Re-index"));
// diagnostic
verbMappings.put("Debug", Arrays.asList("Diagnose"));
verbMappings.put("Measure", Arrays.asList("Calculate", "Determine", "Analyze"));
verbMappings.put("Ping", Arrays.asList());
verbMappings.put("Repair", Arrays.asList("FixRestore"));
verbMappings.put("Resolve", Arrays.asList("ExpandDetermine"));
verbMappings.put("Test", Arrays.asList("Diagnose", "Analyze", "Salvage", "Verify"));
verbMappings.put("Trace", Arrays.asList("Track", "Follow", "Inspect", "Dig"));
// lifecycle
verbMappings.put("Approve", Arrays.asList());
verbMappings.put("Assert", Arrays.asList("Certify"));
verbMappings.put("Build", Arrays.asList());
verbMappings.put("Complete", Arrays.asList());
verbMappings.put("Confirm", Arrays.asList("Acknowledge", "Agree", "Certify", "Validate", "Verify"));
verbMappings.put("Deny", Arrays.asList("Block", "Object", "Refuse", "Reject"));
verbMappings.put("Deploy", Arrays.asList());
verbMappings.put("Disable", Arrays.asList("HaltHide"));
verbMappings.put("Enable", Arrays.asList("StartBegin"));
verbMappings.put("Install", Arrays.asList("Setup"));
verbMappings.put("Invoke", Arrays.asList("RunStart"));
verbMappings.put("Register", Arrays.asList());
verbMappings.put("Request", Arrays.asList());
verbMappings.put("Restart", Arrays.asList("Recycle"));
verbMappings.put("Resume", Arrays.asList());
verbMappings.put("Start", Arrays.asList("Launch", "Initiate", "Boot"));
verbMappings.put("Stop", Arrays.asList("End", "Kill", "Terminate", "Cancel"));
verbMappings.put("Submit", Arrays.asList("Post"));
verbMappings.put("Suspend", Arrays.asList("Pause"));
verbMappings.put("Uninstall", Arrays.asList());
verbMappings.put("Unregister", Arrays.asList("Remove"));
verbMappings.put("Wait", Arrays.asList("SleepPause"));
// security
verbMappings.put("Block", Arrays.asList("Prevent", "Limit", "Deny"));
verbMappings.put("Grant", Arrays.asList("AllowEnable"));
verbMappings.put("Protect", Arrays.asList("Encrypt", "Safeguard", "Seal"));
verbMappings.put("Revoke", Arrays.asList("RemoveDisable"));
verbMappings.put("Unblock", Arrays.asList("ClearAllow"));
verbMappings.put("Unprotect", Arrays.asList("DecryptUnseal"));
// other
verbMappings.put("Use", Arrays.asList());
for (Map.Entry> entry : verbMappings.entrySet()) {
// loop through each verb in the list
for (String verb : entry.getValue()) {
if (verbMappings.containsKey(verb)) {
// the verb to be mapped is also a common verb, do nothing
LOGGER.debug("verbmapping: skipped {}", verb);
} else {
commonVerbs.put(verb, entry.getKey());
LOGGER.debug("verbmapping: adding {} => {}", verb, entry.getKey());
}
}
}
powershellVerbs = new HashSet(Arrays.asList(
"Add",
"Clear",
"Close",
"Copy",
"Enter",
"Exit",
"Find",
"Format",
"Get",
"Hide",
"Join",
"Lock",
"Move",
"New",
"Open",
"Optimize",
"Pop",
"Push",
"Redo",
"Remove",
"Rename",
"Reset",
"Search",
"Select",
"Set",
"Show",
"Skip",
"Split",
"Step",
"Switch",
"Undo",
"Unlock",
"Watch",
"Connect",
"Disconnect",
"Read",
"Receive",
"Send",
"Write",
"Backup",
"Checkpoint",
"Compare",
"Compress",
"Convert",
"ConvertFrom",
"ConvertTo",
"Dismount",
"Edit",
"Expand",
"Export",
"Group",
"Import",
"Initialize",
"Limit",
"Merge",
"Mount",
"Out",
"Publish",
"Restore",
"Save",
"Sync",
"Unpublish",
"Update",
"Debug",
"Measure",
"Ping",
"Repair",
"Resolve",
"Test",
"Trace",
"Approve",
"Assert",
"Build",
"Complete",
"Confirm",
"Deny",
"Deploy",
"Disable",
"Enable",
"Install",
"Invoke",
"Register",
"Request",
"Restart",
"Resume",
"Start",
"Stop",
"Submit",
"Suspend",
"Uninstall",
"Unregister",
"Wait",
"Block",
"Grant",
"Protect",
"Revoke",
"Unblock",
"Unprotect",
"Use"
));
methodNames = new HashSet();
nullablePrimitives = new HashSet(Arrays.asList(
"System.Nullable[Byte]",
"System.Nullable[SByte]",
"System.Nullable[Int16]",
"System.Nullable[Int32]",
"System.Nullable[Int64]",
"System.Nullable[UInt16]",
"System.Nullable[UInt32]",
"System.Nullable[UInt64]",
"System.Nullable[Decimal]",
"System.Nullable[Single]",
"System.Nullable[Double]",
"System.Nullable[Boolean]"
));
// list of reserved words - must be in lower case
reservedWords = new HashSet(Arrays.asList(
// https://richardspowershellblog.wordpress.com/2009/05/02/powershell-reserved-words/
"begin",
"break",
"catch",
"continue",
"data",
"do",
"dynamicparam",
"else",
"elseif",
"end",
"exit",
"filter",
"finally",
"for",
"foreach",
"from",
"function",
"if",
"in",
"param",
"process",
"return",
"switch",
"throw",
"trap",
"try",
"until",
"while",
"local",
"private",
"where",
// special variables
"args",
"consolefilename",
"error",
"event",
"eventargs",
"eventsubscriber",
"executioncontext",
"false",
"foreach",
"home",
"host",
"input",
"lastexitcode",
"matches",
"myinvocation",
"nestedpromptlevel",
"null",
"pid",
"profile",
"pscmdlet",
"pscommandpath",
"psculture",
"psdebugcontext",
"pshome",
"psitem",
"psscriptroot",
"pssenderinfo",
"psuiculture",
"psversiontable",
"sender",
"shellid",
"stacktrace",
"this",
"true"
));
defaultIncludes = new HashSet(Arrays.asList(
"Byte",
"SByte",
"Byte[]",
"Int16",
"Int32",
"Int64",
"UInt16",
"UInt32",
"UInt64",
"Decimal",
"Single",
"Double",
"TimeSpan",
"System.DateTime",
"ProgressRecord",
"Char",
"String",
"XmlDocument",
"SecureString",
"Boolean",
"Guid",
"Uri",
"System.IO.FileInfo",
"Version"
));
typeMapping = new HashMap();
typeMapping.put("string", "String");
typeMapping.put("boolean", "Boolean");
typeMapping.put("integer", "Int32");
typeMapping.put("float", "Double");
typeMapping.put("long", "Int64");
typeMapping.put("double", "Double");
typeMapping.put("number", "Decimal");
typeMapping.put("object", "System.Collections.Hashtable");
typeMapping.put("file", "System.IO.FileInfo");
typeMapping.put("ByteArray", "System.Byte[]");
typeMapping.put("binary", "System.IO.FileInfo");
typeMapping.put("date", "System.DateTime");
typeMapping.put("date-time", "System.DateTime");
typeMapping.put("Date", "System.DateTime");
typeMapping.put("DateTime", "System.DateTime");
typeMapping.put("UUID", "String");
typeMapping.put("URI", "String");
cliOptions.clear();
cliOptions.add(new CliOption("powershellGalleryUrl", "URL to the module in PowerShell Gallery (e.g. https://www.powershellgallery.com/packages/PSTwitter/)."));
cliOptions.add(new CliOption(CodegenConstants.PACKAGE_NAME, "Client package name (e.g. PSTwitter).").defaultValue(this.packageName));
cliOptions.add(new CliOption(CodegenConstants.PACKAGE_VERSION, "Package version (e.g. 0.1.2).").defaultValue(this.packageVersion));
cliOptions.add(new CliOption(CodegenConstants.OPTIONAL_PROJECT_GUID, "GUID for PowerShell module (e.g. a27b908d-2a20-467f-bc32-af6f3a654ac5). A random GUID will be generated by default."));
cliOptions.add(new CliOption(CodegenConstants.API_NAME_PREFIX, "Prefix that will be appended to all PS objects. Default: empty string. e.g. Pet => PSPet."));
cliOptions.add(new CliOption("commonVerbs", "PS common verb mappings. e.g. Delete=Remove:Patch=Update to map Delete with Remove and Patch with Update accordingly."));
cliOptions.add(new CliOption(CodegenConstants.USE_ONEOF_DISCRIMINATOR_LOOKUP, CodegenConstants.USE_ONEOF_DISCRIMINATOR_LOOKUP_DESC));
cliOptions.add(new CliOption("discardReadOnly", "Set discardReadonly to true to generate the Initialize cmdlet without readonly parameters"));
cliOptions.add(new CliOption("tags","Tags applied to the generated PowerShell module. These help with module discovery in online galleries"));
cliOptions.add(new CliOption("projectUri","A URL to the main website for this project"));
cliOptions.add(new CliOption("licenseUri","A URL to the license for the generated PowerShell module"));
cliOptions.add(new CliOption("iconUri","A URL to an icon representing the generated PowerShell module"));
cliOptions.add(new CliOption("releaseNotes","Release notes of the generated PowerShell module"));
cliOptions.add(new CliOption("skipVerbParsing", "Set skipVerbParsing to not try get powershell verbs of operation names"));
// option to change how we process + set the data in the 'additionalProperties' keyword.
CliOption disallowAdditionalPropertiesIfNotPresentOpt = CliOption.newBoolean(
CodegenConstants.DISALLOW_ADDITIONAL_PROPERTIES_IF_NOT_PRESENT,
CodegenConstants.DISALLOW_ADDITIONAL_PROPERTIES_IF_NOT_PRESENT_DESC).defaultValue(Boolean.TRUE.toString());
Map disallowAdditionalPropertiesIfNotPresentOpts = new HashMap<>();
disallowAdditionalPropertiesIfNotPresentOpts.put("false",
"The 'additionalProperties' implementation is compliant with the OAS and JSON schema specifications.");
disallowAdditionalPropertiesIfNotPresentOpts.put("true",
"Keep the old (incorrect) behaviour that 'additionalProperties' is set to false by default.");
disallowAdditionalPropertiesIfNotPresentOpt.setEnum(disallowAdditionalPropertiesIfNotPresentOpts);
cliOptions.add(disallowAdditionalPropertiesIfNotPresentOpt);
this.setDisallowAdditionalPropertiesIfNotPresent(true);
// default value in the template
additionalProperties.put("powershellVersion", "6.2"); // minimal PS version
additionalProperties.put("author", "OpenAPI Generator Team");
additionalProperties.put("companyName", "openapitools.org");
additionalProperties.put("psData", null);
}
public CodegenType getTag() {
return CodegenType.CLIENT;
}
public String getName() {
return "powershell";
}
public String getHelp() {
return "Generates a PowerShell API client (beta)";
}
public void setPackageName(String packageName) {
this.packageName = packageName;
this.apiPackage = packageName + File.separator + "Api";
this.modelPackage = packageName + File.separator + "Model";
}
public void setPackageVersion(String packageVersion) {
this.packageVersion = packageVersion;
}
public void setSourceFolder(String sourceFolder) {
this.sourceFolder = sourceFolder;
}
public void setPackageGuid(String packageGuid) {
this.packageGuid = packageGuid;
}
public void setPowershellGalleryUrl(String powershellGalleryUrl) {
this.powershellGalleryUrl = powershellGalleryUrl;
}
public void setUseOneOfDiscriminatorLookup(boolean useOneOfDiscriminatorLookup) {
this.useOneOfDiscriminatorLookup = useOneOfDiscriminatorLookup;
}
public boolean getUseOneOfDiscriminatorLookup() {
return this.useOneOfDiscriminatorLookup;
}
public void setDiscardReadOnly(boolean discardReadOnly) {
this.discardReadOnly = discardReadOnly;
}
public boolean getDiscardReadOnly() {
return this.discardReadOnly;
}
public void setTags(String tags){
this.tags = tags;
}
public void setLicenseUri(String licenseUri){
this.licenseUri = licenseUri;
}
public void setProjectUri(String projectUri){
this.projectUri = projectUri;
}
public void setReleaseNotes(String releaseNotes){
this.releaseNotes = releaseNotes;
}
public void setIconUri(String iconUri){
this.iconUri = iconUri;
}
public void setSkipVerbParsing(boolean skipVerbParsing) { this.skipVerbParsing = skipVerbParsing; };
@Override
public void processOpts() {
this.setLegacyDiscriminatorBehavior(false);
super.processOpts();
if (StringUtils.isEmpty(System.getenv("POWERSHELL_POST_PROCESS_FILE"))) {
LOGGER.info("Environment variable POWERSHELL_POST_PROCESS_FILE not defined so the PowerShell code may not be properly formatted. To define it, try 'export POWERSHELL_POST_PROCESS_FILE=\"Edit-DTWBeautifyScript\"'");
LOGGER.info("NOTE: To enable file post-processing, 'enablePostProcessFile' must be set to `true` (--enable-post-process-file for CLI).");
}
if (additionalProperties.containsKey("powershellGalleryUrl")) {
setPowershellGalleryUrl((String) additionalProperties.get("powershellGalleryUrl"));
} else {
additionalProperties.put("powershellGalleryUrl", powershellGalleryUrl);
}
if (additionalProperties.containsKey(CodegenConstants.USE_ONEOF_DISCRIMINATOR_LOOKUP)) {
setUseOneOfDiscriminatorLookup(convertPropertyToBooleanAndWriteBack(CodegenConstants.USE_ONEOF_DISCRIMINATOR_LOOKUP));
} else {
additionalProperties.put(CodegenConstants.USE_ONEOF_DISCRIMINATOR_LOOKUP, useOneOfDiscriminatorLookup);
}
if (additionalProperties.containsKey("discardReadOnly")) {
setDiscardReadOnly(convertPropertyToBooleanAndWriteBack("discardReadOnly"));
} else {
additionalProperties.put("discardReadOnly", discardReadOnly);
}
if (additionalProperties.containsKey("skipVerbParsing")) {
setSkipVerbParsing(convertPropertyToBoolean("skipVerbParsing"));
} else {
additionalProperties.put("skipVerbParsing", skipVerbParsing);
}
if (additionalProperties.containsKey("tags")) {
String[] entries = ((String) additionalProperties.get("tags")).split(",");
String prefix = "";
StringBuilder tagStr = new StringBuilder("@(");
for (String entry : entries) {
tagStr.append(prefix);
prefix = ",";
tagStr.append(String.format(Locale.ROOT, "'%s' ",entry));
}
tagStr.append(")");
setTags(tagStr.toString());
additionalProperties.put("tags",tagStr.toString());
}
if (additionalProperties.containsKey("releaseNotes")) {
setReleaseNotes((String) additionalProperties.get("releaseNotes"));
} else {
additionalProperties.put("releaseNotes", releaseNote);
}
if (additionalProperties.containsKey("licenseUri")) {
setLicenseUri((String) additionalProperties.get("licenseUri"));
} else {
additionalProperties.put("licenseUri", licenseUri);
}
if (additionalProperties.containsKey("projectUri")) {
setProjectUri((String) additionalProperties.get("projectUri"));
} else {
additionalProperties.put("projectUri", tags);
}
if (additionalProperties.containsKey("iconUri")) {
setIconUri((String) additionalProperties.get("iconUri"));
} else {
additionalProperties.put("iconUri", iconUri);
}
if (StringUtils.isNotBlank(powershellGalleryUrl)) {
// get the last segment of the URL
// e.g. https://www.powershellgallery.com/packages/PSTwitter => PSTwitter
additionalProperties.put("powershellGalleryId", powershellGalleryUrl.replaceFirst(".*/([^/?]+).*", "$1"));
}
if (additionalProperties.containsKey(CodegenConstants.OPTIONAL_PROJECT_GUID)) {
setPackageGuid((String) additionalProperties.get(CodegenConstants.OPTIONAL_PROJECT_GUID));
} else {
additionalProperties.put("packageGuid", packageGuid);
}
if (additionalProperties.containsKey(CodegenConstants.PACKAGE_NAME)) {
this.setPackageName((String) additionalProperties.get(CodegenConstants.PACKAGE_NAME));
} else {
additionalProperties.put(CodegenConstants.PACKAGE_NAME, packageName);
}
if (additionalProperties.containsKey(CodegenConstants.PACKAGE_VERSION)) {
this.setPackageVersion((String) additionalProperties.get(CodegenConstants.PACKAGE_VERSION));
} else {
additionalProperties.put(CodegenConstants.PACKAGE_VERSION, packageVersion);
}
if (additionalProperties.containsKey("commonVerbs")) {
String[] entries = ((String) additionalProperties.get("commonVerbs")).split(":");
for (String entry : entries) {
String[] pair = entry.split("=");
if (pair.length == 2) {
commonVerbs.put(pair[0], pair[1]);
LOGGER.debug("Add commonVerbs: {} => {}", pair[0], pair[1]);
} else {
LOGGER.error("Failed to parse commonVerbs: {}", entry);
}
}
}
if (additionalProperties.containsKey(CodegenConstants.MODEL_PACKAGE)) {
LOGGER.warn(CodegenConstants.MODEL_PACKAGE + " with " + this.getName() + " generator is ignored. Setting this value independently of " + CodegenConstants.PACKAGE_NAME + " is not currently supported.");
}
if (additionalProperties.containsKey(CodegenConstants.API_PACKAGE)) {
LOGGER.warn(CodegenConstants.API_PACKAGE + " with " + this.getName() + " generator is ignored. Setting this value independently of " + CodegenConstants.PACKAGE_NAME + " is not currently supported.");
}
if (additionalProperties.containsKey(CodegenConstants.DISALLOW_ADDITIONAL_PROPERTIES_IF_NOT_PRESENT)) {
this.setDisallowAdditionalPropertiesIfNotPresent(Boolean.valueOf(additionalProperties
.get(CodegenConstants.DISALLOW_ADDITIONAL_PROPERTIES_IF_NOT_PRESENT).toString()));
}
additionalProperties.put(CodegenConstants.API_PACKAGE, apiPackage());
additionalProperties.put(CodegenConstants.MODEL_PACKAGE, modelPackage());
additionalProperties.put("apiDocPath", apiDocPath);
additionalProperties.put("modelDocPath", modelDocPath);
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
supportingFiles.add(new SupportingFile("Build.ps1.mustache", "", "Build.ps1"));
final String infrastructureFolder = (sourceFolder + File.separator + packageName + File.separator);
supportingFiles.add(new SupportingFile("Org.OpenAPITools.psm1.mustache", infrastructureFolder, packageName + ".psm1"));
// client/configuration
supportingFiles.add(new SupportingFile("configuration.mustache", infrastructureFolder + "Client", apiNamePrefix + "Configuration.ps1"));
// private
supportingFiles.add(new SupportingFile("api_client.mustache", infrastructureFolder + "Private", apiNamePrefix + "ApiClient.ps1"));
supportingFiles.add(new SupportingFile("Get-CommonParameters.mustache", infrastructureFolder + File.separator + "Private" + File.separator, "Get-CommonParameters.ps1"));
supportingFiles.add(new SupportingFile("Out-DebugParameter.mustache", infrastructureFolder + File.separator + "Private" + File.separator, "Out-DebugParameter.ps1"));
supportingFiles.add(new SupportingFile("http_signature_auth.mustache", infrastructureFolder + "Private", apiNamePrefix + "HttpSignatureAuth.ps1"));
supportingFiles.add(new SupportingFile("rsa_provider.mustache", infrastructureFolder + "Private", apiNamePrefix + "RSAEncryptionProvider.cs"));
// en-US
supportingFiles.add(new SupportingFile("about_Org.OpenAPITools.help.txt.mustache", infrastructureFolder + File.separator + "en-US" + File.separator + "about_" + packageName + ".help.txt"));
// appveyor
supportingFiles.add(new SupportingFile("appveyor.mustache", "", "appveyor.yml"));
}
@SuppressWarnings("static-method")
@Override
public String escapeText(String input) {
if (input == null) {
return input;
}
// remove \t, \n, \r
// replace \ with \\
// replace " with \"
// outter unescape to retain the original multi-byte characters
// finally escalate characters avoiding code injection
return escapeUnsafeCharacters(
StringEscapeUtils.unescapeJava(
StringEscapeUtils.escapeJava(input)
.replace("\\/", "/"))
.replaceAll("[\\t\\n\\r]", " ")
.replace("\"", "\"\""));
}
@Override
public String escapeUnsafeCharacters(String input) {
return input.replace("#>", "#_>").replace("<#", "<_#");
}
@Override
public String escapeQuotationMark(String input) {
// remove " to avoid code injection
return input.replace("\"", "");
}
@Override
public String toApiTestFilename(String name) {
return toApiFilename(name) + ".Tests";
}
@Override
public String toModelTestFilename(String name) {
return toModelFilename(name) + ".Tests";
}
@Override
public String apiTestFileFolder() {
return (outputFolder + "/" + apiTestPath).replace('/', File.separatorChar);
}
@Override
public String apiDocFileFolder() {
return (outputFolder + "/" + apiDocPath).replace('/', File.separatorChar);
}
@Override
public String apiFileFolder() {
return outputFolder + File.separator + sourceFolder + File.separator + apiPackage();
}
@Override
public String modelTestFileFolder() {
return (outputFolder + "/" + modelTestPath).replace('/', File.separatorChar);
}
@Override
public String modelDocFileFolder() {
return (outputFolder + "/" + modelDocPath).replace('/', File.separatorChar);
}
@Override
public String modelFileFolder() {
return outputFolder + File.separator + sourceFolder + File.separator + modelPackage();
}
@Override
public String escapeReservedWord(String name) {
return "Var" + name;
}
/**
* Output the proper model name (capitalized).
* In case the name belongs to the TypeSystem it won't be renamed.
*
* @param name the name of the model
* @return capitalized model name
*/
@Override
public String toModelName(String name) {
if (!StringUtils.isEmpty(modelNamePrefix)) {
name = modelNamePrefix + "_" + name;
}
if (!StringUtils.isEmpty(modelNameSuffix)) {
name = name + "_" + modelNameSuffix;
}
// camelize the model name
// phone_number => PhoneNumber
name = camelize(sanitizeName(name));
// model name cannot use reserved keyword, e.g. return
if (isReservedWord(name)) {
LOGGER.warn(name + " (reserved word or special variable name) cannot be used as model name. Renamed to " + camelize("model_" + name));
name = camelize("model_" + name); // e.g. return => ModelReturn (after camelize)
}
// model name starts with number
if (name.matches("^\\d.*")) {
LOGGER.warn(name + " (model name starts with number) cannot be used as model name. Renamed to " + camelize("model_" + name));
name = camelize("model_" + name); // e.g. 200Response => Model200Response (after camelize)
}
return name;
}
@Override
public String toModelFilename(String name) {
// should be the same as the model name
return toModelName(name);
}
/**
* returns the OpenAPI type for the property
*
* @param p OpenAPI property object
* @return string presentation of the type
**/
@Override
public String getSchemaType(Schema p) {
String openAPIType = super.getSchemaType(p);
String type;
// This maps, for example, long -> Long based on hashes in this type's constructor
if (typeMapping.containsKey(openAPIType)) {
type = typeMapping.get(openAPIType);
if (languageSpecificPrimitives.contains(type)) {
return type;
}
} else {
type = openAPIType;
}
// model/object
return toModelName(type);
}
/**
* Output the type declaration of the property
*
* @param p OpenAPI Schema object
* @return a string presentation of the property type
*/
@Override
public String getTypeDeclaration(Schema p) {
if (ModelUtils.isArraySchema(p)) {
ArraySchema ap = (ArraySchema) p;
Schema inner = ap.getItems();
return getTypeDeclaration(inner) + "[]";
} else if (ModelUtils.isMapSchema(p)) {
return "System.Collections.Hashtable";
} else if (!languageSpecificPrimitives.contains(getSchemaType(p))) {
return super.getTypeDeclaration(p);
}
return super.getTypeDeclaration(p);
}
@Override
public String toOperationId(String operationId) {
// throw exception if method name is empty (should not occur as an auto-generated method name will be used)
if (StringUtils.isEmpty(operationId)) {
throw new RuntimeException("Empty method name (operationId) not allowed");
}
return sanitizeName(operationId);
}
@Override
public String toParamName(String name) {
return toVarName(name);
}
@Override
public Map postProcessOperationsWithModels(Map objs, List allModels) {
Map operations = (Map) objs.get("operations");
HashMap modelMaps = new HashMap();
HashMap processedModelMaps = new HashMap();
for (Object o : allModels) {
HashMap h = (HashMap) o;
CodegenModel m = (CodegenModel) h.get("model");
modelMaps.put(m.classname, m);
}
List operationList = (List) operations.get("operation");
for (CodegenOperation op : operationList) {
int index = 0;
for (CodegenParameter p : op.allParams) {
p.vendorExtensions.put("x-powershell-data-type", getPSDataType(p));
p.vendorExtensions.put("x-powershell-example", constructExampleCode(p, modelMaps, processedModelMaps));
p.vendorExtensions.put("x-index", index);
index++;
}
if (!op.vendorExtensions.containsKey("x-powershell-method-name")) { // x-powershell-method-name not set
String methodName = toMethodName(op.operationId);
op.vendorExtensions.put("x-powershell-method-name", methodName);
op.vendorExtensions.put("x-powershell-method-name-lowercase", methodName);
} else {
op.vendorExtensions.put("x-powershell-method-name-lowercase", ((String) op.vendorExtensions.get("x-powershell-method-name")).toLowerCase(Locale.ROOT));
}
// detect duplicated method name
if (methodNames.contains(op.vendorExtensions.get("x-powershell-method-name"))) {
LOGGER.error("Duplicated method name found: {}", op.vendorExtensions.get("x-powershell-method-name"));
} else {
methodNames.add(op.vendorExtensions.get("x-powershell-method-name"));
}
if (op.produces != null && op.produces.size() > 1) {
op.vendorExtensions.put("x-powershell-select-accept", true);
}
}
processedModelMaps.clear();
for (CodegenOperation operation : operationList) {
for (CodegenParameter cp : operation.allParams) {
cp.vendorExtensions.put("x-powershell-example", constructExampleCode(cp, modelMaps, processedModelMaps));
}
}
// check if return type is oneOf/anyeOf model
for (CodegenOperation op : operationList) {
if (op.returnType != null) {
// look up the model to see if it's anyOf/oneOf
if (modelMaps.containsKey(op.returnType) && modelMaps.get(op.returnType) != null) {
CodegenModel cm = modelMaps.get(op.returnType);
if (cm.oneOf != null && !cm.oneOf.isEmpty()) {
op.vendorExtensions.put("x-ps-return-type-one-of", true);
}
if (cm.anyOf != null && !cm.anyOf.isEmpty()) {
op.vendorExtensions.put("x-ps-return-type-any-of", true);
}
} else {
//LOGGER.error("cannot lookup model " + op.returnType);
}
}
}
return objs;
}
@Override
public Map postProcessModels(Map objs) {
List models = (List) objs.get("models");
// add x-index to properties
ProcessUtils.addIndexToProperties(models);
// add x-data-type to store powershell type
for (Object _mo : models) {
Map _model = (Map) _mo;
CodegenModel model = (CodegenModel) _model.get("model");
CodegenProperty lastWritableProperty = null;
for (CodegenProperty cp : model.allVars) {
cp.vendorExtensions.put("x-powershell-data-type", getPSDataType(cp));
if (this.discardReadOnly && !cp.isReadOnly) {
lastWritableProperty = cp;
}
}
// Mark the last readonly false property
if (this.discardReadOnly && lastWritableProperty != null) {
lastWritableProperty.vendorExtensions.put("x-powershell-last-writable", true);
model.allVars.set(model.allVars.indexOf(lastWritableProperty), lastWritableProperty);
}
// if oneOf contains "null" type
if (model.oneOf != null && !model.oneOf.isEmpty() && model.oneOf.contains("ModelNull")) {
model.isNullable = true;
model.oneOf.remove("ModelNull");
}
// if anyOf contains "null" type
if (model.anyOf != null && !model.anyOf.isEmpty() && model.anyOf.contains("ModelNull")) {
model.isNullable = true;
model.anyOf.remove("ModelNull");
}
}
return objs;
}
@Override
public String toVarName(String name) {
// sanitize name
name = sanitizeName(name);
// camelize the variable name
// pet_id => PetId
name = camelize(name);
// for reserved word or word starting with number, append _
if (isReservedWord(name) || name.matches("^\\d.*")) {
LOGGER.warn(name + " (reserved word or special variable name) cannot be used in naming. Renamed to " + escapeReservedWord(name));
name = escapeReservedWord(name);
}
return name;
}
private String constructExampleCode(CodegenParameter codegenParameter, HashMap modelMaps, HashMap processedModelMap) {
if (codegenParameter.isArray) { // array
return "@(" + constructExampleCode(codegenParameter.items, modelMaps, processedModelMap) + ")";
} else if (codegenParameter.isMap) { // TODO: map, file type
return "@{ \"Key\" = \"Value\" }";
} else if (languageSpecificPrimitives.contains(codegenParameter.dataType) ||
nullablePrimitives.contains(codegenParameter.dataType)) { // primitive type
if ("String".equals(codegenParameter.dataType) || "Character".equals(codegenParameter.dataType)) {
if (StringUtils.isEmpty(codegenParameter.example)) {
return "\"" + codegenParameter.example + "\"";
} else {
if (Boolean.TRUE.equals(codegenParameter.isEnum)) { // enum
List enumValues = (List) codegenParameter.allowableValues.get("values");
return "\"" + String.valueOf(enumValues.get(0)) + "\"";
} else {
return "\"" + codegenParameter.paramName + "_example\"";
}
}
} else if ("Boolean".equals(codegenParameter.dataType) ||
"System.Nullable[Boolean]".equals(codegenParameter.dataType)) { // boolean
if (Boolean.parseBoolean(codegenParameter.example)) {
return "true";
} else {
return "false";
}
} else if ("URL".equals(codegenParameter.dataType)) { // URL
return "URL(string: \"https://example.com\")!";
} else if ("System.DateTime".equals(codegenParameter.dataType)) { // datetime or date
return "Get-Date";
} else { // numeric
if (StringUtils.isEmpty(codegenParameter.example)) {
return codegenParameter.example;
} else {
return "987";
}
}
} else { // model
// look up the model
if (modelMaps.containsKey(codegenParameter.dataType)) {
return constructExampleCode(modelMaps.get(codegenParameter.dataType), modelMaps, processedModelMap);
} else {
//LOGGER.error("Error in constructing examples. Failed to look up the model " + codegenParameter.dataType);
return "TODO";
}
}
}
private String constructExampleCode(CodegenProperty codegenProperty, HashMap modelMaps, HashMap processedModelMap) {
if (codegenProperty.isArray) { // array
return "@(" + constructExampleCode(codegenProperty.items, modelMaps, processedModelMap) + ")";
} else if (codegenProperty.isMap) { // map
return "\"TODO\"";
} else if (languageSpecificPrimitives.contains(codegenProperty.dataType) || // primitive type
nullablePrimitives.contains(codegenProperty.dataType)) { // nullable primitive type
if ("String".equals(codegenProperty.dataType)) {
if (StringUtils.isEmpty(codegenProperty.example)) {
return "\"" + codegenProperty.example + "\"";
} else {
if (Boolean.TRUE.equals(codegenProperty.isEnum)) { // enum
List enumValues = (List) codegenProperty.allowableValues.get("values");
return "\"" + String.valueOf(enumValues.get(0)) + "\"";
} else {
return "\"" + codegenProperty.name + "_example\"";
}
}
} else if ("Boolean".equals(codegenProperty.dataType) ||
"System.Nullable[Boolean]".equals(codegenProperty.dataType)) { // boolean
if (Boolean.parseBoolean(codegenProperty.example)) {
return "$true";
} else {
return "$false";
}
} else if ("URL".equals(codegenProperty.dataType)) { // URL
return "URL(string: \"https://example.com\")!";
} else if ("System.DateTime".equals(codegenProperty.dataType)) { // datetime or date
return "Get-Date";
} else { // numeric
if (StringUtils.isEmpty(codegenProperty.example)) {
return codegenProperty.example;
} else {
return "123";
}
}
} else {
// look up the model
if (modelMaps.containsKey(codegenProperty.dataType)) {
return constructExampleCode(modelMaps.get(codegenProperty.dataType), modelMaps, processedModelMap);
} else {
//LOGGER.error("Error in constructing examples. Failed to look up the model " + codegenProperty.dataType);
return "\"TODO\"";
}
}
}
private String constructExampleCode(CodegenModel codegenModel, HashMap modelMaps, HashMap processedModelMap) {
String example;
// break infinite recursion. Return, in case a model is already processed in the current context.
String model = codegenModel.name;
if (processedModelMap.containsKey(model)) {
int count = processedModelMap.get(model);
if (count == 1) {
processedModelMap.put(model, 2);
} else if (count == 2) {
return "";
} else {
throw new RuntimeException("Invalid count when constructing example: " + count);
}
} else {
processedModelMap.put(model, 1);
}
example = "(Initialize-" + codegenModel.name + " ";
List propertyExamples = new ArrayList<>();
for (CodegenProperty codegenProperty : codegenModel.allVars) {
propertyExamples.add("-" + codegenProperty.name + " " + constructExampleCode(codegenProperty, modelMaps, processedModelMap));
}
example += StringUtils.join(propertyExamples, " ");
example += ")";
return example;
}
private String getPSDataType(CodegenProperty cp) {
String dataType;
if (cp.isPrimitiveType) {
dataType = cp.dataType;
if (!(cp.isString || cp.isFile || cp.isContainer)
&& (cp.isNullable || !cp.required)) {
dataType = "System.Nullable[" + dataType + "]";
}
return dataType;
} else if (cp.isArray) { // array
return getPSDataType(cp.items) + "[]";
} else if (cp.isMap) { // map
return "System.Collections.Hashtable";
} else { // model
return "PSCustomObject";
}
}
private String getPSDataType(CodegenParameter cp) {
String dataType;
if (cp.isPrimitiveType) {
dataType = cp.dataType;
if (!(cp.isString || cp.isFile || cp.isContainer)
&& (cp.isNullable || !cp.required)) {
dataType = "System.Nullable[" + dataType + "]";
}
return dataType;
} else if (cp.isArray) { // array
return getPSDataType(cp.items) + "[]";
} else if (cp.isMap) { // map
return "System.Collections.Hashtable";
} else { // model
return "PSCustomObject";
}
}
private String toMethodName(String operationId) {
String methodName = camelize(operationId);
if (!skipVerbParsing) {
// check if method name starts with powershell verbs
for (String verb : (HashSet) powershellVerbs) {
if (methodName.startsWith(verb)) {
methodName = verb + "-" + apiNamePrefix + methodName.substring(verb.length());
LOGGER.info("Naming the method using the PowerShell verb: {} => {}", operationId, methodName);
return methodName;
}
}
for (Map.Entry entry : commonVerbs.entrySet()) {
if (methodName.startsWith(entry.getKey())) {
methodName = entry.getValue() + "-" + apiNamePrefix + methodName.substring(entry.getKey().length());
LOGGER.info("Naming the method by mapping the common verbs (e.g. Create, Change) to PS verbs: {} => {}", operationId, methodName);
return methodName;
}
}
}
// not using powershell verb
return "Invoke-" + apiNamePrefix + methodName;
}
@Override
public void postProcessFile(File file, String fileType) {
if (file == null) {
return;
}
String powershellPostProcessFile = System.getenv("POWERSHELL_POST_PROCESS_FILE");
if (StringUtils.isEmpty(powershellPostProcessFile)) {
return; // skip if POWERSHELL_POST_PROCESS_FILE env variable is not defined
}
// only process files with ps extension
if ("ps".equals(FilenameUtils.getExtension(file.toString()))) {
String command = powershellPostProcessFile + " " + file.toString();
try {
Process p = Runtime.getRuntime().exec(command);
int exitValue = p.waitFor();
if (exitValue != 0) {
LOGGER.error("Error running the command ({}). Exit value: {}", command, exitValue);
} else {
LOGGER.info("Successfully executed: " + command);
}
} catch (Exception e) {
LOGGER.error("Error running the command ({}). Exception: {}", command, e.getMessage());
}
}
}
@Override
public String toRegularExpression(String pattern) {
return escapeText(pattern);
}
@Override
public String toDefaultValue(Schema p) {
if (p.getDefault() != null) {
if (ModelUtils.isBooleanSchema(p)) {
if (Boolean.valueOf(p.getDefault().toString())) {
return "$true";
} else {
return "$false";
}
} else if (ModelUtils.isDateSchema(p)) {
LOGGER.warn("Default value for `date` not yet supported. Please open an issue with https://github.com/openapitools/openapi-generator");
} else if (ModelUtils.isDateTimeSchema(p)) {
LOGGER.warn("Default value for `datetime` not yet supported. Please open an issue with https://github.com/openapitools/openapi-generator");
} else if (ModelUtils.isNumberSchema(p)) {
return p.getDefault().toString();
} else if (ModelUtils.isIntegerSchema(p)) {
return p.getDefault().toString();
} else if (ModelUtils.isStringSchema(p)) {
return "\"" + p.getDefault() + "\"";
}
}
return null;
}
}