Skip to content

Commit a14b7a6

Browse files
authored
Merge pull request #452 from RachelTucker/SA-217
SA-217: Adding type converter to parser module
2 parents 11f0d82 + 9d8e5f1 commit a14b7a6

File tree

10 files changed

+452
-3
lines changed

10 files changed

+452
-3
lines changed

ds3-autogen-net/src/test/java/com/spectralogic/ds3autogen/net/NetFunctionalTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1205,7 +1205,7 @@ public void getTapesWithFullDetails_Test() throws TemplateModelException, IOExce
12051205
assertTrue(TestHelper.hasOptionalParam(requestName, "SerialNumber", "string", requestCode));
12061206
assertTrue(TestHelper.hasOptionalParam(requestName, "State", "TapeState", requestCode));
12071207
assertTrue(TestHelper.hasOptionalParam(requestName, "StorageDomainId", "Guid", requestCode));
1208-
assertTrue(TestHelper.hasOptionalParam(requestName, "Type", "TapeType", requestCode));
1208+
assertTrue(TestHelper.hasOptionalParam(requestName, "Type", "string", requestCode));
12091209
assertTrue(TestHelper.hasOptionalParam(requestName, "WriteProtected", "bool", requestCode));
12101210

12111211
assertTrue(TestHelper.hasConstructor(requestName, ImmutableList.of(), requestCode));

ds3-autogen-parser/src/main/java/com/spectralogic/ds3autogen/Ds3SpecNormalizer.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import com.spectralogic.ds3autogen.api.models.apispec.Ds3ApiSpec;
2020
import com.spectralogic.ds3autogen.api.models.apispec.Ds3Request;
2121
import com.spectralogic.ds3autogen.api.models.apispec.Ds3ResponseCode;
22+
import com.spectralogic.ds3autogen.converters.TypeConverter;
2223

2324
import static com.spectralogic.ds3autogen.converters.NameConverter.renameRequests;
2425
import static com.spectralogic.ds3autogen.converters.RemoveDollarSignConverter.removeDollarSigns;
@@ -48,11 +49,15 @@ public static Ds3ApiSpec convertSpec(
4849
final Ds3ApiSpec spec,
4950
final boolean generateInternal) {
5051
verifySingleResponsePayloadRequests(spec.getRequests());
51-
return updateElementsInSpec( //Updates Ds3Elements to account for ExcludeFromMarshaler values
52+
53+
final TypeConverter typeConverter = new TypeConverter();
54+
55+
return typeConverter.modifyTypes( //Converts contract types to sdk types as specified in file typeMap.json
56+
updateElementsInSpec( //Updates Ds3Elements to account for ExcludeFromMarshaler values
5257
renameRequests( //Rename requests from RequestHandler to Request
5358
convertResponseTypes( //Converts response types with components into new encapsulating types
5459
removeDollarSigns( //Converts all type names containing '$' into proper type names
55-
removeInternalRequestsFromSpec(spec, generateInternal))))); //Removes/keeps spectra internal requests
60+
removeInternalRequestsFromSpec(spec, generateInternal)))))); //Removes/keeps spectra internal requests
5661
}
5762

5863
/**
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* ******************************************************************************
3+
* Copyright 2014-2017 Spectra Logic Corporation. All Rights Reserved.
4+
* Licensed under the Apache License, Version 2.0 (the "License"). You may not use
5+
* this file except in compliance with the License. A copy of the License is located at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* or in the "license" file accompanying this file.
10+
* This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
11+
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
12+
* specific language governing permissions and limitations under the License.
13+
* ****************************************************************************
14+
*/
15+
16+
package com.spectralogic.ds3autogen.models.xml.typemap;
17+
18+
import com.fasterxml.jackson.annotation.JsonProperty;
19+
import com.google.common.collect.ImmutableList;
20+
import com.google.common.collect.ImmutableMap;
21+
22+
public class TypeMap {
23+
24+
@JsonProperty("TypeMap")
25+
private ImmutableList<TypeMapElement> typeMap;
26+
27+
public ImmutableMap<String, String> toMap() {
28+
final ImmutableMap.Builder<String, String> builder = ImmutableMap.builder();
29+
typeMap.forEach(element -> builder.put(element.getContractType(), element.getSdkType()));
30+
return builder.build();
31+
}
32+
33+
public void setTypeMap(ImmutableList<TypeMapElement> typeMap) {
34+
this.typeMap = typeMap;
35+
}
36+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package com.spectralogic.ds3autogen.models.xml.typemap;
2+
3+
import com.fasterxml.jackson.annotation.JsonProperty;
4+
5+
public class TypeMapElement {
6+
7+
@JsonProperty("ContractType")
8+
private String contractType;
9+
10+
@JsonProperty("SdkType")
11+
private String sdkType;
12+
13+
public String getContractType() {
14+
return contractType;
15+
}
16+
17+
public void setContractType(String contractType) {
18+
this.contractType = contractType;
19+
}
20+
21+
public String getSdkType() {
22+
return sdkType;
23+
}
24+
25+
public void setSdkType(String sdkType) {
26+
this.sdkType = sdkType;
27+
}
28+
}
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
/*
2+
* ******************************************************************************
3+
* Copyright 2014-2017 Spectra Logic Corporation. All Rights Reserved.
4+
* Licensed under the Apache License, Version 2.0 (the "License"). You may not use
5+
* this file except in compliance with the License. A copy of the License is located at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* or in the "license" file accompanying this file.
10+
* This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
11+
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
12+
* specific language governing permissions and limitations under the License.
13+
* ****************************************************************************
14+
*/
15+
16+
package com.spectralogic.ds3autogen.converters
17+
18+
import com.google.common.collect.ImmutableList
19+
import com.google.common.collect.ImmutableMap
20+
import com.spectralogic.ds3autogen.api.models.apispec.*
21+
import com.spectralogic.ds3autogen.typemap.SdkTypeMapper
22+
import com.spectralogic.ds3autogen.utils.ConverterUtil.isEmpty
23+
import com.spectralogic.ds3autogen.utils.collections.GuavaCollectors
24+
25+
/**
26+
* Modifies contract types into sdk types as specified within the Ds3ApiSpec.
27+
* This affects types within request parameters, response types, and response payload elements.
28+
* @param typeMapper maps contract type names to be changed into sdk types for code generation
29+
*/
30+
class TypeConverter(private val typeMapper: SdkTypeMapper) {
31+
constructor(): this(SdkTypeMapper()) // Uses the default type mapper
32+
33+
fun modifyTypes(spec: Ds3ApiSpec): Ds3ApiSpec {
34+
typeMapper.init()
35+
return Ds3ApiSpec(updateDs3Requests(spec.requests), updateDs3TypeMap(spec.types))
36+
}
37+
38+
private fun updateDs3Requests(ds3requests: ImmutableList<Ds3Request>?): ImmutableList<Ds3Request> {
39+
if (isEmpty(ds3requests)) {
40+
return ImmutableList.of()
41+
}
42+
return ds3requests!!.stream()
43+
.map(this::updateDs3Request)
44+
.collect(GuavaCollectors.immutableList())
45+
}
46+
47+
private fun updateDs3Request(ds3Request: Ds3Request): Ds3Request {
48+
return Ds3Request(
49+
ds3Request.name,
50+
ds3Request.httpVerb,
51+
ds3Request.classification,
52+
ds3Request.bucketRequirement,
53+
ds3Request.objectRequirement,
54+
ds3Request.action,
55+
ds3Request.resource,
56+
ds3Request.resourceType,
57+
ds3Request.operation,
58+
ds3Request.includeInPath,
59+
updateResposneCodes(ds3Request.ds3ResponseCodes),
60+
updateParams(ds3Request.optionalQueryParams),
61+
updateParams(ds3Request.requiredQueryParams)
62+
)
63+
}
64+
65+
private fun updateParams(params: ImmutableList<Ds3Param>?): ImmutableList<Ds3Param> {
66+
if (isEmpty(params)) {
67+
return ImmutableList.of()
68+
}
69+
70+
return params!!.stream()
71+
.map { param -> Ds3Param(param.name, typeMapper.toType(param.type), param.nullable) }
72+
.collect(GuavaCollectors.immutableList())
73+
}
74+
75+
private fun updateResposneCodes(responseCodes: ImmutableList<Ds3ResponseCode>?): ImmutableList<Ds3ResponseCode> {
76+
if (isEmpty(responseCodes)) {
77+
return ImmutableList.of()
78+
}
79+
80+
return responseCodes!!.stream()
81+
.map { code -> Ds3ResponseCode(code.code, updateResponseTypes(code.ds3ResponseTypes)) }
82+
.collect(GuavaCollectors.immutableList())
83+
}
84+
85+
private fun updateResponseTypes(responseTypes: ImmutableList<Ds3ResponseType>?): ImmutableList<Ds3ResponseType> {
86+
if (isEmpty(responseTypes)) {
87+
return ImmutableList.of()
88+
}
89+
90+
return responseTypes!!.stream()
91+
.map { responseType -> Ds3ResponseType(
92+
typeMapper.toType(responseType.type),
93+
typeMapper.toNullableType(responseType.componentType),
94+
responseType.originalTypeName) }
95+
.collect(GuavaCollectors.immutableList())
96+
}
97+
98+
private fun updateDs3TypeMap(typeMap: ImmutableMap<String, Ds3Type>?): ImmutableMap<String, Ds3Type> {
99+
if (isEmpty(typeMap)) {
100+
return ImmutableMap.of()
101+
}
102+
103+
val builder = ImmutableMap.builder<String, Ds3Type>()
104+
typeMap!!.forEach { name, type -> builder.put(name, updateDs3Type(type)) }
105+
106+
return builder.build()
107+
}
108+
109+
private fun updateDs3Type(ds3Type: Ds3Type): Ds3Type {
110+
return Ds3Type(
111+
ds3Type.name,
112+
ds3Type.nameToMarshal,
113+
updateDs3Elements(ds3Type.elements),
114+
ds3Type.enumConstants
115+
)
116+
}
117+
118+
private fun updateDs3Elements(elements: ImmutableList<Ds3Element>?): ImmutableList<Ds3Element> {
119+
if (isEmpty(elements)) {
120+
return ImmutableList.of()
121+
}
122+
123+
return elements!!.stream()
124+
.map { element -> Ds3Element(
125+
element.name,
126+
typeMapper.toNullableType(element.type),
127+
typeMapper.toNullableType(element.componentType),
128+
element.ds3Annotations,
129+
element.nullable
130+
) }
131+
.collect(GuavaCollectors.immutableList())
132+
}
133+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/*
2+
* ******************************************************************************
3+
* Copyright 2014-2017 Spectra Logic Corporation. All Rights Reserved.
4+
* Licensed under the Apache License, Version 2.0 (the "License"). You may not use
5+
* this file except in compliance with the License. A copy of the License is located at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* or in the "license" file accompanying this file.
10+
* This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
11+
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
12+
* specific language governing permissions and limitations under the License.
13+
* ****************************************************************************
14+
*/
15+
16+
package com.spectralogic.ds3autogen.typemap
17+
18+
import com.fasterxml.jackson.databind.ObjectMapper
19+
import com.fasterxml.jackson.datatype.guava.GuavaModule
20+
import com.spectralogic.ds3autogen.models.xml.typemap.TypeMap
21+
import com.spectralogic.ds3autogen.utils.ConverterUtil.isEmpty
22+
23+
private const val DEFAULT_TYPE_MAP_FILE = "/typeMap.json"
24+
25+
/**
26+
* Used to map contract types into sdk types. This is used when the
27+
* provided contract type is to be overridden with a manually determined type.
28+
*/
29+
class SdkTypeMapper(private val typeMapFileName: String) {
30+
constructor() : this(DEFAULT_TYPE_MAP_FILE)
31+
32+
/** map of contract names to be changed (keys), into sdk types (values) */
33+
private lateinit var typeMapper: Map<String, String>
34+
35+
/**
36+
* Initialize the type mapper via parsing the json file containing the type re-mapping
37+
*/
38+
fun init() {
39+
val stream = SdkTypeMapper::class.java.getResourceAsStream(typeMapFileName)
40+
val objectMapper = ObjectMapper()
41+
objectMapper.registerModule(GuavaModule())
42+
typeMapper = objectMapper.readValue<TypeMap>(stream, TypeMap::class.java).toMap()
43+
}
44+
45+
/**
46+
* Returns the sdk type to be generated from the contract type. If there is no type
47+
* mapping, then the original string is returned.
48+
*/
49+
fun toType(contractType: String): String {
50+
val curType = contractType.substringAfterLast('.')
51+
return if (typeMapper.containsKey(curType)) typeMapper[curType]!! else contractType
52+
}
53+
54+
fun toNullableType(contractType: String?): String? {
55+
if (isEmpty(contractType)) {
56+
return contractType
57+
}
58+
return toType(contractType!!)
59+
}
60+
61+
/**
62+
* Retrieves the underlying map used in the re-typing process. This is used for testing.
63+
*/
64+
fun getMap(): Map<String, String> = typeMapper
65+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"TypeMap": [
3+
{
4+
"ContractType": "TapeType",
5+
"SdkType": "java.lang.String"
6+
}
7+
]
8+
}

0 commit comments

Comments
 (0)