Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for string array type in endpoint parameter #3085

Merged
merged 36 commits into from
Sep 6, 2024
Merged

Add support for string array type in endpoint parameter #3085

merged 36 commits into from
Sep 6, 2024

Conversation

sbera87
Copy link
Contributor

@sbera87 sbera87 commented Aug 22, 2024

Issue #, if available:

Description of changes:

Check all that applies:

  • Did a review by yourself.
  • Added proper tests to cover this PR. (If tests are not applicable, explain.)
  • Checked if this PR is a breaking (APIs have been changed) change.
  • Checked if this PR will not introduce cross-platform inconsistent behavior.
  • Checked if this PR would require a ReadMe/Wiki update.

Check which platforms you have built SDK on to verify the correctness of this PR.

  • Linux
  • Windows
  • Android
  • MacOS
  • IOS
  • Other Platforms

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

@@ -0,0 +1,93 @@

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess you created a separate package for this test suite and forgot to delete this file.
Please remove this file if so.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ack

@@ -225,21 +225,21 @@ public SdkFileEntry[] generateSourceFiles(ServiceModel serviceModel) throws Exce
});

serviceModel.getOperations().values().stream()
.filter(operationEntry -> operationEntry.getName().equals("WriteGetObjectResponse"))
.filter(operationEntry -> operationEntry != null && operationEntry.getName() != null && "WriteGetObjectResponse".equals(operationEntry.getName() ))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure why this piece of legacy code needs to be updated for the given feature.
Please provide some context.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Initially I used S3 client to create the blob and found some null checks missing, so added it . But this is not necessary as with null operation name, we expect to fail

@@ -9,28 +10,55 @@

import java.lang.reflect.Type;
import java.util.Map;
import java.util.Vector;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think most of the SDK code gen uses java's List and ArrayList, I don't think "synchronization" feature of java's Vector is needed here.
I let Sam comment and provide guidance here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ack. you are correct

'q','u','i','r','e','d','"',':','t','r','u','e',',','"','d','e','f','a','u','l','t','"',':','[','"',
'd','e','f','a','u','l','t','V','a','l','u','e','1','"',',','"','d','e','f','a','u','l','t','V','a',
'l','u','e','2','"',']',',','"','d','o','c','u','m','e','n','t','a','t','i','o','n','"',':','"','d',
'o','c','s','"','}','}',',','"','r','u','l','e','s','"',':','[','{','"','d','o','c','u','m','e','n',
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

blob generated from codegen on rules json with test staticontext params

}

private static final class CppEndpointsJmesPathVisitor implements
software.amazon.smithy.jmespath.ExpressionVisitor<Pair<String, Shape>>
Copy link
Contributor Author

@sbera87 sbera87 Sep 1, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For example, the path expression
"keys(map)"
Where json:
"MapOperationRequest": {
"type": "structure",
"members": {
"map":{"shape":"Map"}
}
},
"Map":{
"type":"map",
"key":{"shape":"String"},
"value":{"shape":"String"}
},
will cause the code to generate

MapOperationRequest::EndpointParameters MapOperationRequest::GetEndpointContextParams() const
{
    EndpointParameters parameters;
    //operation context params go here
    parameters.emplace_back(Aws::String{"stringArrayParam"}, this->GetOperationContextParams(), Aws::Endpoint::EndpointParameter::ParameterOrigin::OPERATION_CONTEXT);
    return parameters;
}
//Accessor for dynamic context endpoint params
Aws::Vector<Aws::String> MapOperationRequest::GetOperationContextParams() const{
  Aws::Vector<Aws::String> result;
  auto& mapElem = (*this).GetMap();
  for (auto& keysElem : mapElem)
  {
  	result.emplace_back(keysElem.first);
  }
  return result;
}```

{
final OperationContextCppCodeGenerator context;
final Shape input;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another example for autogenerated code for jmespath expression "nested.listOfObjects[*].key"
where json is:
"ListOfObjectsOperationRequest": {
"type": "structure",
"members": {
"nested":{"shape":"Nested"}
}
},
"Nested": {
"type": "structure",
"members": {
"listOfObjects":{"shape":"ListOfObjects"}
}
},
"ListOfObjects": {
"type": "list",
"member":{"shape":"ObjectMember"}
},
"ObjectMember": {
"type": "structure",
"members": {
"key":{"shape":"String"}
}
},

Code:
ListOfObjectsOperationRequest::EndpointParameters ListOfObjectsOperationRequest::GetEndpointContextParams() const
{
    EndpointParameters parameters;
    //operation context params go here
    parameters.emplace_back(Aws::String{"stringArrayParam"}, this->GetOperationContextParams(), Aws::Endpoint::EndpointParameter::ParameterOrigin::OPERATION_CONTEXT);
    return parameters;
}
//Accessor for dynamic context endpoint params
Aws::Vector<Aws::String> ListOfObjectsOperationRequest::GetOperationContextParams() const{
  Aws::Vector<Aws::String> result;
  auto& nestedElem = (*this).GetNested().GetListOfObjects();
  for (auto& listOfObjectsElem : nestedElem)
  {
  	auto& keyElem = listOfObjectsElem.GetKey();
  	result.emplace_back(keyElem);
  }
  return result;
}

@sbera87 sbera87 changed the title add support for string array type in endpoint parameter [Work in Progress] Add support for string array type in endpoint parameter Sep 1, 2024
Copy link
Contributor

@sbiscigl sbiscigl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove commented code, unused code/changes, and white space changes


auto res = endpointProvider_sp->ResolveEndpoint(parameters);
EXPECT_TRUE(res.IsSuccess());
//std::cout<<"url="<<res.GetResult().GetURL()<<std::endl;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove commented out std::out

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ack

tools/code-generation/generator/pom.xml Show resolved Hide resolved
@sbiscigl
Copy link
Contributor

sbiscigl commented Sep 4, 2024

Please remove commented code, unused code/changes, and white space changes

please look through the PR and remove white space changes, commented, code, and comments in files that have no code changes

@@ -11,6 +11,7 @@
import java.util.List;
import java.util.Map;


Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

white space

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ack

}
ParameterType type;
Boolean boolValue;
Integer intValue;
String strValue;
ArrayList<String> strArrayValue;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

never use ArrayList, use List or Collection, the actual underlying impl should not be a member variable type

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

got it, will change

operation.setStaticContextParams(c2jOperation.getStaticContextParams());

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

white space and comment without changed code

@@ -22,6 +24,23 @@ public String getValue() throws Exception {
} else if (ParameterType.STRING == this.type) {
String strValueEscaped = (strValue.contains("\"") || strValue.contains("\\")) ? "R\"(" + strValue + ")\"" : "\"" + strValue + "\"";
return strValueEscaped;
} else if (ParameterType.STRING_ARRAY == this.type){
StringBuilder sb = new StringBuilder();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

using a string builder and a for loop is a little old fashioned we should be using a streaming and joining that to a formatted string i.e.

public static final String AWS_VECTOR_FORMAT = "Aws::Vector<Aws::String>{%s}";
if (...) {
 ...
} else if (ParameterType.STRING_ARRAY == this.type){
  final String values = strArrayValue.stream()
    .map(elem -> (elem.contains("\"") || elem.contains("\\"))
      ? "R\"(" + elem + ")\""
      : "\"" + elem + "\"")
     .collect(Collectors.joining(","));
  return String.format(AWS_VECTOR_FORMAT, values);
 }
...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it. Will change

}
@Override
public Pair<String, Shape> visitProjection(ProjectionExpression expression) {
Pair<String, Shape> left = expression.getLeft().accept(this);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lets modernize this and use streams

return Optional.of(expression.getLeft().accept(this))
  .filter(shape -> shape.right.isList())
  .map(shape -> {
    String varName =  shape.left + "Elem";
    context.rangeBasedForLoop(varName);
    context.openVariableScope(varName);
    Pair<String, Shape> right = expression.getRight().accept( new CppEndpointsJmesPathVisitor(context, shape.right.getListMember().getShape()));
    context.closeVariableScope();
    return Pair.of(shape.left,right.right);
  })
  .orElseThrow(() -> new SmithyBuildException("Unsupported JMESPath expression"));


}

class DynamoDBEndpointProviderTest : public Aws::Endpoint::DefaultEndpointProvider<>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: rename it without dynamo

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ack

@@ -33,7 +33,7 @@ namespace Aws
void SetParameter(EndpointParameter param);
void SetStringParameter(Aws::String name, Aws::String value);
void SetBooleanParameter(Aws::String name, bool value);

void SetStringArrayParameter(Aws::String name, const Aws::Vector<Aws::String>&& value);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what is the point of const r-value reference?
I think "pass-by-value and move" or "pass-by-const-rer and copy; pass-by-rval and move" are the most common ways, while the first is the shortest one (in terms of number of methods written)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry missed this comment, this is a typo, i will make a pr to fix this

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a huge deal, can be dealt with some other next pr.

@@ -28,6 +28,7 @@ namespace Aws
void SetParameter(EndpointParameter param);
void SetStringParameter(Aws::String name, Aws::String value);
void SetBooleanParameter(Aws::String name, bool value);
void SetStringArrayParameter(Aws::String name, const Aws::Vector<Aws::String>& value);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: inconsistent style with the previous diff.

AWS_LOGSTREAM_TRACE(DEFAULT_ENDPOINT_PROVIDER_TAG,
"Endpoint str array eval parameter: " <<
parameter.GetName() << " = " <<
[]() -> Aws::OStringStream {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I miss something here, but how does this lambda work without capturing parameter?

@sbera87 sbera87 merged commit d759f4a into main Sep 6, 2024
4 checks passed
@sbera87 sbera87 deleted the array branch September 6, 2024 01:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants