-
Notifications
You must be signed in to change notification settings - Fork 15
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
Adds changes for sequence data type #144
Merged
desaikd
merged 3 commits into
amazon-ion:new-model-changes
from
desaikd:model-sequence-changes
Sep 25, 2024
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
type::{ | ||
name: sequence, | ||
type: list, | ||
element: string | ||
} |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
68 changes: 35 additions & 33 deletions
68
src/bin/ion/commands/generate/templates/java/sequence.templ
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,81 +1,83 @@ | ||
package {{ namespace }}; | ||
import java.util.ArrayList; | ||
{% macro sequence(model) %} | ||
|
||
{% if is_nested == false %} | ||
{% set full_namespace = namespace | join(sep=".") %} | ||
|
||
package {{ full_namespace }}; | ||
import com.amazon.ion.IonReader; | ||
import com.amazon.ion.IonException; | ||
import com.amazon.ion.IonWriter; | ||
import com.amazon.ion.IonType; | ||
import java.io.IOException; | ||
{% endif %} | ||
|
||
{# Verify that the abstract data type is a sequence type and store information for this sequence value #} | ||
{% set sequence_info = model.code_gen_type["WrappedSequence"] %} | ||
|
||
public class {{ target_kind_name }} { | ||
private {{ fields[0].value_type }} value; | ||
class {{ model.name }} { | ||
private java.util.ArrayList<{{ sequence_info["element_type"] | fully_qualified_type_name }}> value; | ||
|
||
public {{ target_kind_name }}() {} | ||
public {{ model.name }}() {} | ||
|
||
public {{ fields[0].value_type }} getValue() { | ||
public java.util.ArrayList<{{ sequence_info["element_type"] | fully_qualified_type_name }}> getValue() { | ||
return this.value; | ||
} | ||
|
||
public void setValue({{ fields[0].value_type }} value) { | ||
public void setValue(java.util.ArrayList<{{ sequence_info["element_type"] | fully_qualified_type_name }}> value) { | ||
this.value = value; | ||
return; | ||
} | ||
|
||
/** | ||
* Reads a {{ target_kind_name }} from an {@link IonReader}. | ||
* Reads a {{ model.name }} from an {@link IonReader}. | ||
* | ||
* This method does not advance the reader at the current level. | ||
* The caller is responsible for positioning the reader on the value to read. | ||
*/ | ||
public static {{ target_kind_name }} readFrom(IonReader reader) { | ||
public static {{ model.name }} readFrom(IonReader reader) { | ||
{# Initializes all the fields of this class #} | ||
{{ fields[0].value_type }} value = | ||
{% if fields[0].value_type == "boolean" %} | ||
false | ||
{% elif fields[0].value_type == "int" or fields[0].value_type == "double" %} | ||
0 | ||
{% else %} | ||
null | ||
{% endif %}; | ||
java.util.ArrayList<{{ sequence_info["element_type"] | fully_qualified_type_name }}> value = new java.util.ArrayList<{{ sequence_info["element_type"] | fully_qualified_type_name }}>(); | ||
{# Reads `Sequence` class with a single field `value` that is an `ArrayList` #} | ||
if(reader.getType() != IonType.{{ abstract_data_type["Sequence"].sequence_type | upper }}) { | ||
throw new IonException("Expected {{ abstract_data_type["Sequence"].sequence_type }}, found " + reader.getType() + " while reading {{ fields[0].name | camel }}."); | ||
if(reader.getType() != IonType.{{ sequence_info["sequence_type"] | upper }}) { | ||
throw new IonException("Expected {{ sequence_info["sequence_type"] }}, found " + reader.getType() + " while reading value."); | ||
} | ||
reader.stepIn(); | ||
value = new {{ fields[0].value_type }}(); | ||
{# Iterate through the `ArrayList` and read each element in it based on the data type provided in `abstract_data_type[Sequence]` #} | ||
{# Iterate through the `ArrayList` and read each element in it based on the data type provided in `sequence_info["sequence_type"]` #} | ||
while (reader.hasNext()) { | ||
reader.next(); | ||
{% if abstract_data_type["Sequence"].element_type | is_built_in_type == false %} | ||
value.add({{ abstract_data_type["Sequence"].element_type }}.readFrom(reader)); | ||
{% elif abstract_data_type["Sequence"].element_type == "bytes[]" %} | ||
{% if sequence_info["element_type"] |fully_qualified_type_name | is_built_in_type == false %} | ||
value.add({{ sequence_info["element_type"] | fully_qualified_type_name }}.readFrom(reader)); | ||
{% elif sequence_info["element_type"] | fully_qualified_type_name == "bytes[]" %} | ||
value.add(reader.newBytes()); | ||
{% else %} | ||
value.add(reader.{{ abstract_data_type["Sequence"].element_type | camel }}Value()); | ||
value.add(reader.{{ sequence_info["element_type"] | fully_qualified_type_name | camel }}Value()); | ||
{% endif %} | ||
} | ||
reader.stepOut(); | ||
{{ target_kind_name }} {{ target_kind_name | camel }} = new {{ target_kind_name }}(); | ||
{{ target_kind_name | camel }}.value = value; | ||
{{ model.name }} {{ model.name | camel }} = new {{ model.name }}(); | ||
{{ model.name | camel }}.value = value; | ||
|
||
return {{ target_kind_name | camel }}; | ||
return {{ model.name | camel }}; | ||
} | ||
|
||
/** | ||
* Writes a {{ target_kind_name }} as Ion from an {@link IonWriter}. | ||
* Writes a {{ model.name }} as Ion from an {@link IonWriter}. | ||
* | ||
* This method does not close the writer after writing is complete. | ||
* The caller is responsible for closing the stream associated with the writer. | ||
*/ | ||
public void writeTo(IonWriter writer) throws IOException { | ||
{# Writes `Sequence` class with a single field `value` that is an `ArrayList` as an Ion sequence #} | ||
writer.stepIn(IonType.{{ abstract_data_type["Sequence"].sequence_type | upper }}); | ||
for ({{ abstract_data_type["Sequence"].element_type }} value: this.value) { | ||
{% if abstract_data_type["Sequence"].element_type | is_built_in_type == false %} | ||
writer.stepIn(IonType.{{ sequence_info["sequence_type"] | upper }}); | ||
for ({{ sequence_info["element_type"] | fully_qualified_type_name }} value: this.value) { | ||
{% if sequence_info["element_type"] | fully_qualified_type_name | is_built_in_type == false %} | ||
value.writeTo(writer); | ||
{% else %} | ||
writer.write{{ abstract_data_type["Sequence"].element_type | upper_camel }}(value); | ||
writer.write{{ sequence_info["element_type"] | fully_qualified_type_name | replace(from="double", to="float") | replace(from="boolean", to="bool") | upper_camel }}(value); | ||
{% endif %} | ||
} | ||
writer.stepOut(); | ||
} | ||
} | ||
{% endmacro %} | ||
{{ self::sequence(model=model) }} |
32 changes: 17 additions & 15 deletions
32
src/bin/ion/commands/generate/templates/java/util_macros.templ
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,34 +1,36 @@ | ||
{# following macro defines statements to read a class field as sequence #} | ||
{% macro read_as_sequence(field) %} | ||
new {{ field.value_type }}(); | ||
{% macro read_as_sequence(field_name, field_value, type_store) %} | ||
{% set field_value_model = type_store[field_value] %} | ||
new {{ field_value }}(); | ||
{# Reads `Sequence` field that is an `ArrayList` #} | ||
if(reader.getType() != IonType.{{ field.abstract_data_type["Sequence"].sequence_type | upper }}) { | ||
throw new IonException("Expected {{ field.abstract_data_type["Sequence"].sequence_type }}, found " + reader.getType() + " while reading {{ field.name | camel }}."); | ||
if(reader.getType() != IonType.{{ field_value_model.code_gen_type["Sequence"].sequence_type | upper }}) { | ||
throw new IonException("Expected {{ field_value_model.code_gen_type["Sequence"].sequence_type }}, found " + reader.getType() + " while reading {{ field_name | camel }}."); | ||
} | ||
reader.stepIn(); | ||
{# Iterate through the `ArrayList` and read each element in it based on the data type provided in `field.abstract_data_type[Sequence]` #} | ||
while (reader.hasNext()) { | ||
reader.next(); | ||
{% if field.abstract_data_type["Sequence"].element_type | is_built_in_type == false %} | ||
{{ field.name | camel }}.add({{ field.abstract_data_type["Sequence"].element_type }}.readFrom(reader)); | ||
{% elif field.abstract_data_type["Sequence"].element_type == "bytes[]" %} | ||
{{ field.name | camel }}.add(reader.newBytes()); | ||
{% if field_value_model.code_gen_type["Sequence"].element_type | fully_qualified_type_name | is_built_in_type == false %} | ||
{{ field_name | camel }}.add({{ field_value_model.code_gen_type["Sequence"].element_type }}.readFrom(reader)); | ||
{% elif field_value_model.code_gen_type["Sequence"].element_type == "bytes[]" %} | ||
{{ field_name | camel }}.add(reader.newBytes()); | ||
{% else %} | ||
{{ field.name | camel }}.add(reader.{{ field.abstract_data_type["Sequence"].element_type | camel }}Value()); | ||
{{ field_name | camel }}.add(reader.{{ field_value_model.code_gen_type["Sequence"].element_type | fully_qualified_type_name | camel }}Value()); | ||
{% endif %} | ||
} | ||
reader.stepOut(); | ||
{% endmacro %} | ||
{# following macro defines statements to write a class field as sequence #} | ||
{% macro write_as_sequence(field) %} | ||
{% macro write_as_sequence(field_name, field_value, type_store) %} | ||
{% set field_value_model = type_store[field_value] %} | ||
{# Writes `Sequence` field that is an `ArrayList` as an Ion sequence #} | ||
writer.stepIn(IonType.{{ field.abstract_data_type["Sequence"].sequence_type | upper }}); | ||
for ({{ field.abstract_data_type["Sequence"].element_type }} value: this.{{ field.name |camel }}) { | ||
{% if field.abstract_data_type["Sequence"].element_type | is_built_in_type == false %} | ||
writer.stepIn(IonType.{{ field_value_model.code_gen_type["Sequence"].sequence_type | upper }}); | ||
for ({{ field_value_model.code_gen_type["Sequence"].element_type | fully_qualified_type_name }} value: this.{{ field_name |camel }}) { | ||
{% if field_value_model.code_gen_type["Sequence"].element_type | fully_qualified_type_name | is_built_in_type == false %} | ||
value.writeTo(writer); | ||
{% else %} | ||
writer.write{{ field.abstract_data_type["Sequence"].element_type | upper_camel }}(value); | ||
writer.write{{ field_value_model.code_gen_type["Sequence"].element_type | fully_qualified_type_name | replace(from="double", to="float") | replace(from="boolean", to="bool") | upper_camel }}(value); | ||
{% endif %} | ||
} | ||
writer.stepOut(); | ||
{% endmacro %} | ||
{% endmacro %} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are we going to have to create corresponding
Wrapped*
variants for all of the non-wrapped variants? Why/why not?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No. I think its in general there are only 3 types structure, sequence and scalar. Where only nested structure would have a name but scalar and sequence would not have name. Hence to separate out whether they are named or not I have them as a separate variant. I think having them separate allows us to perform specific operations for these types which will be stored as property instead of entirely different class in the generated code.
e.g. For below ISL:
Here's the generated code in Java:
whereas for structure type like following:
Here's the generated code in Java, which creates a new nested type for this nested structure:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we really need the non-wrapped variant of sequence? We have parameterized, fully-qualified type references, so we should be able to model the non-wrapped lists as e.g.
java.util.List<org.example.MyGeneratedClass>
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
WrpapedSequence
useFullyQualifiedTypeName
(notFullyqualifiedTypeReference
). AndWrappedSequence
have a name, for example:Above wrapped sequence's name will be stored as
org.example.Foo
.Whereas
Sequence
would not have a name, for example:We can surely store it as fully-qualified type references and thats what we already we store the
element
property asFullyWualfiiedTypeReference
and then when storing this type intoTypeStore
we usejava.util.ArrayList<String>
but it still wouldn't have name (like the wrapped sequence has name asfoo
)There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, but the non-wrapped version (
Sequence
) does not have a name and does not have a class generated for it. Therefore, why do we need to have the unnamedSequence
model? You don't need a reference to theSequence
when you can just use a parameterized reference such asjava.util.ArrayList<java.lang.String>
.For example, if you have this schema, the
{ type: list, element: string }
does not need aSequence
to be created to represent it. Instead, the fieldbar
should have the data model equivalent of a reference tojava.util.ArrayList<java.lang.String>
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have created an issue for this: #145. Need to look at if removing the non-wrapped variants has any requirements for how they are rendered in templates.