1 /* 2 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"). 5 * You may not use this file except in compliance with the License. 6 * A copy of the License is located at 7 * 8 * http://aws.amazon.com/apache2.0 9 * 10 * or in the "license" file accompanying this file. This file is distributed 11 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 12 * express or implied. See the License for the specific language governing 13 * permissions and limitations under the License. 14 */ 15 16 package software.amazon.awssdk.codegen; 17 18 import java.util.Collections; 19 import java.util.Optional; 20 import java.util.stream.Collectors; 21 import software.amazon.awssdk.codegen.internal.Constant; 22 import software.amazon.awssdk.codegen.model.config.customization.CustomizationConfig; 23 import software.amazon.awssdk.codegen.model.intermediate.Metadata; 24 import software.amazon.awssdk.codegen.model.intermediate.Protocol; 25 import software.amazon.awssdk.codegen.model.service.AuthType; 26 import software.amazon.awssdk.codegen.model.service.ServiceMetadata; 27 import software.amazon.awssdk.codegen.model.service.ServiceModel; 28 import software.amazon.awssdk.codegen.naming.DefaultNamingStrategy; 29 import software.amazon.awssdk.codegen.naming.NamingStrategy; 30 import software.amazon.awssdk.utils.Pair; 31 import software.amazon.awssdk.utils.StringUtils; 32 33 /** 34 * Constructs the metadata that is required for generating the java client from the service meta data. 35 */ 36 final class AddMetadata { 37 private static final String AWS_PACKAGE_PREFIX = "software.amazon.awssdk.services"; 38 AddMetadata()39 private AddMetadata() { 40 } 41 42 constructMetadata(ServiceModel serviceModel, CustomizationConfig customizationConfig)43 public static Metadata constructMetadata(ServiceModel serviceModel, 44 CustomizationConfig customizationConfig) { 45 Metadata metadata = new Metadata(); 46 47 NamingStrategy namingStrategy = new DefaultNamingStrategy(serviceModel, customizationConfig); 48 ServiceMetadata serviceMetadata = serviceModel.getMetadata(); 49 String serviceName = namingStrategy.getServiceName(); 50 51 configurePackageName(metadata, namingStrategy, customizationConfig); 52 53 metadata.withApiVersion(serviceMetadata.getApiVersion()) 54 .withAsyncClient(String.format(Constant.ASYNC_CLIENT_CLASS_NAME_PATTERN, serviceName)) 55 .withAsyncInterface(String.format(Constant.ASYNC_CLIENT_INTERFACE_NAME_PATTERN, serviceName)) 56 .withAsyncBuilder(String.format(Constant.ASYNC_BUILDER_CLASS_NAME_PATTERN, serviceName)) 57 .withAsyncBuilderInterface(String.format(Constant.ASYNC_BUILDER_INTERFACE_NAME_PATTERN, serviceName)) 58 .withBaseBuilderInterface(String.format(Constant.BASE_BUILDER_INTERFACE_NAME_PATTERN, serviceName)) 59 .withBaseBuilder(String.format(Constant.BASE_BUILDER_CLASS_NAME_PATTERN, serviceName)) 60 .withDocumentation(serviceModel.getDocumentation()) 61 .withServiceAbbreviation(serviceMetadata.getServiceAbbreviation()) 62 .withServiceFullName(serviceMetadata.getServiceFullName()) 63 .withServiceName(serviceName) 64 .withSyncClient(String.format(Constant.SYNC_CLIENT_CLASS_NAME_PATTERN, serviceName)) 65 .withSyncInterface(String.format(Constant.SYNC_CLIENT_INTERFACE_NAME_PATTERN, serviceName)) 66 .withSyncBuilder(String.format(Constant.SYNC_BUILDER_CLASS_NAME_PATTERN, serviceName)) 67 .withSyncBuilderInterface(String.format(Constant.SYNC_BUILDER_INTERFACE_NAME_PATTERN, serviceName)) 68 .withBaseExceptionName(String.format(Constant.BASE_EXCEPTION_NAME_PATTERN, serviceName)) 69 .withBaseRequestName(String.format(Constant.BASE_REQUEST_NAME_PATTERN, serviceName)) 70 .withBaseResponseName(String.format(Constant.BASE_RESPONSE_NAME_PATTERN, serviceName)) 71 .withProtocol(Protocol.fromValue(serviceMetadata.getProtocol())) 72 .withJsonVersion(serviceMetadata.getJsonVersion()) 73 .withEndpointPrefix(serviceMetadata.getEndpointPrefix()) 74 .withSigningName(serviceMetadata.getSigningName()) 75 .withAuthType(AuthType.fromValue(serviceMetadata.getSignatureVersion())) 76 .withUid(serviceMetadata.getUid()) 77 .withServiceId(serviceMetadata.getServiceId()) 78 .withSupportsH2(supportsH2(serviceMetadata)) 79 .withJsonVersion(getJsonVersion(metadata, serviceMetadata)) 80 .withAwsQueryCompatible(serviceMetadata.getAwsQueryCompatible()) 81 .withAuth(Optional.ofNullable(serviceMetadata.getAuth()) 82 .orElseGet(() -> Collections.singletonList(serviceMetadata.getSignatureVersion())) 83 .stream() 84 .map(AuthType::fromValue) 85 .collect(Collectors.toList())); 86 87 return metadata; 88 } 89 configurePackageName(Metadata metadata, NamingStrategy namingStrategy, CustomizationConfig customizationConfig)90 private static void configurePackageName(Metadata metadata, 91 NamingStrategy namingStrategy, 92 CustomizationConfig customizationConfig) { 93 String packageName = customizationConfig.getRootPackageName(); 94 95 Optional<Pair<String, String>> packageNamePair = splitCustomRootPackageName(packageName); 96 String rootPackageWithoutServiceId = packageNamePair.map(pkg -> StringUtils.lowerCase(pkg.left())) 97 .orElse(AWS_PACKAGE_PREFIX); 98 99 String service = packageNamePair.map(pkg -> StringUtils.lowerCase(pkg.right())) 100 .orElse(namingStrategy.getServiceName()); 101 102 metadata.withRootPackageName(rootPackageWithoutServiceId) 103 .withClientPackageName(namingStrategy.getClientPackageName(service)) 104 .withModelPackageName(namingStrategy.getModelPackageName(service)) 105 .withTransformPackageName(namingStrategy.getTransformPackageName(service)) 106 .withRequestTransformPackageName(namingStrategy.getRequestTransformPackageName(service)) 107 .withPaginatorsPackageName(namingStrategy.getPaginatorsPackageName(service)) 108 .withWaitersPackageName(namingStrategy.getWaitersPackageName(service)) 109 .withEndpointRulesPackageName(namingStrategy.getEndpointRulesPackageName(service)) 110 .withAuthSchemePackageName(namingStrategy.getAuthSchemePackageName(service)); 111 } 112 113 /** 114 * Split the root package to [prefix].[suffix] pair. For example: "software.amazon.awssdk.services.s3" will be split into 115 * "software.amazon.awssdk.services" and "s3". 116 */ splitCustomRootPackageName(String rootPackageName)117 public static Optional<Pair<String, String>> splitCustomRootPackageName(String rootPackageName) { 118 if (rootPackageName == null) { 119 return Optional.empty(); 120 } 121 122 int i = rootPackageName.lastIndexOf('.'); 123 return Optional.of(Pair.of(rootPackageName.substring(0, i), rootPackageName.substring(i + 1, rootPackageName.length()))); 124 } 125 supportsH2(ServiceMetadata serviceMetadata)126 private static boolean supportsH2(ServiceMetadata serviceMetadata) { 127 return serviceMetadata.getProtocolSettings() != null && serviceMetadata.getProtocolSettings().containsKey("h2"); 128 } 129 getJsonVersion(Metadata metadata, ServiceMetadata serviceMetadata)130 private static String getJsonVersion(Metadata metadata, ServiceMetadata serviceMetadata) { 131 // TODO this should be defaulted in the C2J build tool 132 if (serviceMetadata.getJsonVersion() == null && metadata.isJsonProtocol()) { 133 return "1.1"; 134 } else { 135 return serviceMetadata.getJsonVersion(); 136 } 137 } 138 } 139