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

RESTWS-904 Support custom representation for Map objects #602

Merged
merged 1 commit into from
Jul 29, 2024

Conversation

gayanW
Copy link
Member

@gayanW gayanW commented Mar 28, 2024

Description of what I changed

This issue is that, ConversionUtil#convertToRepresentation(object, representation, converter), does not use the representation param, when the object param is of type Map. So it'll always return an object with all the elements in the map, even if the caller wants to convert it to a custom representation.

public static <S> Object convertToRepresentation(S o, Representation rep, Converter specificConverter)
throws ConversionException {
if (o == null)
return null;
o = new HibernateLazyLoader().load(o);
if (o instanceof Collection) {
List ret = new ArrayList();
for (Object item : ((Collection) o)) {
ret.add(convertToRepresentation(item, rep, specificConverter));
}
return ret;
} else if (o instanceof Map) {
SimpleObject ret = new SimpleObject();
for (Map.Entry<?, ?> entry : ((Map<?, ?>) o).entrySet()) {
ret.put(entry.getKey().toString(),
convertToRepresentation(entry.getValue(), Representation.REF, (Converter) null));
}
return ret;

As shown below every value in the map is converted to it's REF representation.

for (Map.Entry<?, ?> entry : ((Map<?, ?>) o).entrySet()) {
ret.put(entry.getKey().toString(),
convertToRepresentation(entry.getValue(), Representation.REF, (Converter) null));

auditInfo objects are of type Map, hence facing the same issue as reported in RESTWS-904

This PR refactors ConversionUtil, so objects of type Map can be converted to custom representations.

Issue I worked on

see https://openmrs.atlassian.net/browse/RESTWS-904

Checklist: I completed these to help reviewers :)

  • My IDE is configured to follow the code style of this project.

    No? Unsure? -> configure your IDE, format the code and add the changes with git add . && git commit --amend

  • I have added tests to cover my changes. (If you refactored
    existing code that was well tested you do not have to add tests)

    No? -> write tests and add them to this commit git add . && git commit --amend

  • I ran mvn clean package right before creating this pull request and
    added all formatting changes to my commit.

    No? -> execute above command

  • All new and existing tests passed.

    No? -> figure out why and add the fix to your commit. It is your responsibility to make sure your code works.

  • My pull request is based on the latest changes of the master branch.

    No? Unsure? -> execute command git pull --rebase upstream master

@gayanW
Copy link
Member Author

gayanW commented Apr 2, 2024

@dkayiwa
It's ready to be reviewed :)

* This could be used to convert any domain objects that does not have any specific converter associated with them
* such as SimpleObject's, Map's, etc
*/
private static SimpleObject convertToRepresentation(Object o, CustomRepresentation rep) {
Copy link
Member

@dkayiwa dkayiwa Apr 2, 2024

Choose a reason for hiding this comment

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

Is there any reason why the method name is generic, yet from the description, you are dealing with only custom representations?

Copy link
Member Author

@gayanW gayanW Apr 3, 2024

Choose a reason for hiding this comment

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

I did think about that a bit. I thought of overloading the method, to make it consistent with the rest of the methods.

If the concern is that, calls to convertToRepresentation resolving to a wrong method, we could refactor the method name. Since this method is private, there's no such thing from happening, though.

Would you like make it more specific like convertToCustomRepresentation?

I don't have a preference on which one to use :)

Copy link
Member

@dkayiwa dkayiwa Apr 4, 2024

Choose a reason for hiding this comment

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

If it cannot deal with any representation but custom, then i would have the name explicitly state that.

Copy link
Member Author

Choose a reason for hiding this comment

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

I refactored the method name.

@@ -168,4 +168,21 @@ public void shouldReturnTheAuditInfoForTheFullRepresentation() throws Exception

assertNotNull(PropertyUtils.getProperty(result, "auditInfo"));
}

@Test
public void shouldReturnCustomRepresentationForAuditInfo() throws Exception {
Copy link
Member

Choose a reason for hiding this comment

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

Shouldn't this be in ConversionUtilTest?

Copy link
Member Author

Choose a reason for hiding this comment

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

PatientIdentifierTypeController1_8Test also include a test named shouldReturnTheAuditInfoForTheFullRepresentation. So it's nice to have a matching E2E test for converting to a custom representation.

The new method that we introuduced in ConversionUtil is private. So I think it makes sense to have it here instead.

Copy link
Member

Choose a reason for hiding this comment

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

Are you directly calling this private method from the test?

Copy link
Member Author

@gayanW gayanW Apr 12, 2024

Choose a reason for hiding this comment

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

No, the private method is not called directly in the test. The test makes a GET call to the resource with custom representation as the v param.

SimpleObject result = deserialize(
handle(newGetRequest(getURI() + "/" + getUuid(),
new Parameter("v", "custom:(auditInfo:(creator:(uuid),dateCreated))"))));

Assertions in this test should be enough to prevent someone from breaking things again :)

Copy link
Member Author

Choose a reason for hiding this comment

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

And the private method is fully covered by this test.

Copy link
Member

Choose a reason for hiding this comment

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

If the test is for a change in ConversionUtil, is there a reason why you do not put the test in ConversionUtilTest?

Copy link
Member

Choose a reason for hiding this comment

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

@gayanW did you see the above comment?

Copy link
Member Author

Choose a reason for hiding this comment

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

Sorry for the late reply. I've been busy with work.

I don't think it would be good to put Mock Http test in ConversionUtil.

Additionally I could write a new unit test for ConversionUtil#convertToRepresentation in ConversionUtilTest. Let me check that on the weekend.

Copy link
Member Author

Choose a reason for hiding this comment

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

I added a new unit test to ConversionUtilTest.

Copy link
Member Author

Choose a reason for hiding this comment

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

@dkayiwa Can you check :)

@@ -145,6 +148,26 @@ public void convert_shouldConvertToAClass() throws Exception {
Assert.assertTrue(converted.isAssignableFrom(String.class));
}

@Test
public void convert_shouldConvertSimpleObjectToCustomRepresentation() throws Exception {
Copy link
Member

Choose a reason for hiding this comment

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

The method name does not seem to reflect the work being done by the ticket?

Copy link
Member Author

Choose a reason for hiding this comment

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

The ticket is about not being able to get custom representations with audit info. auditInfo is a simple object that implements map interface.

So bassically it's enough to assert that it can properly convert simple objects to a given custom representation.

Copy link
Member Author

Choose a reason for hiding this comment

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

@dkayiwa Can we merge this fix?

@dkayiwa dkayiwa merged commit 70882a4 into openmrs:master Jul 29, 2024
1 check passed
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.

2 participants