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

Fixed JSON annotations to enable ODE processing of circle geometries #114

Open
wants to merge 7 commits into
base: dev
Choose a base branch
from

Conversation

dmccoystephenson
Copy link
Member

@dmccoystephenson dmccoystephenson commented Nov 4, 2024

PR Details

Description

Problem

When preparing a TIM for encoding by translating it to XML, the position element is mistakenly added to the circle element. This occurs because a JSON property annotation incorrectly assigns position to the getter for the center element of circle.

Solution

The issue was resolved by updating the Circle subclass of Asn1Object to use consistent JSON property annotations for the center element.

Related Issue

Motivation and Context

As per J2735, the ODE should be capable of processing circle geometries for TIMs.

How Has This Been Tested?

A TIM request with a circle geometry of the following form was sent to the /tim endpoint:

"geometry": {
  "direction": "1111000011110000",
  "circle": {
    "center": {
      "latitude": "41.153593",
      "longitude": "-104.655785",
      "elevation": "1824"
    },
    "radius": "50",
    "units": "3"
  }
},

Given this input, the ODE produced input XER for the AEM that it was able to process.

A new unit test has been added to verify that the TimTransmogrifier correctly converts a TIM with circle geometry to XML. The test prepares input data similarly to the TimDepositController, though the setup in the unit test is slightly simplified. While further refactoring of the data preparation process would be beneficial, it is outside the scope of this fix.

It is recommended to set the 'show whitespace' option to false when reviewing the TimTransmogrifierTest file.
image

Types of changes

  • Defect fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that cause existing functionality to change)

Checklist:

  • I have added any new packages to the sonar-scanner.properties file
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have read the CONTRIBUTING document.
    ODE Contributing Guide
  • I have added tests to cover my changes.
  • All new and existing tests passed.


@JsonProperty("position")
Copy link
Member Author

Choose a reason for hiding this comment

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

note: this is the offending annotation that caused the problem

Choose a reason for hiding this comment

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

Can we add a unit test for this use case?

Copy link
Member Author

Choose a reason for hiding this comment

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

Added!

Copy link

Choose a reason for hiding this comment

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

Is position an invalid property on a Circle Asn1Object in all cases, or is there any scenario where we want to have position present? I'm gathering that, at minimum, we don't want both position and center present, but is there a scenario where we could want position present when center is not (and vice versa)?

Copy link
Member Author

Choose a reason for hiding this comment

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

Is position an invalid property on a Circle Asn1Object in all cases, or is there any scenario where we want to have position present? I'm gathering that, at minimum, we don't want both position and center present, but is there a scenario where we could want position present when center is not (and vice versa)?

The ASN.1 representation for a Circle in J2735 only contains center, radius and units. I don't think we'll ever have a scenario where we want to have 'position' present.

Copy link

@Michael7371 Michael7371 left a comment

Choose a reason for hiding this comment

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

I was able to verify that circle TIM's process properly and that unit tests all pass. My only comment is that we should add a unit test to cover this bug fix.


@JsonProperty("position")

Choose a reason for hiding this comment

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

Can we add a unit test for this use case?

@dmccoystephenson dmccoystephenson marked this pull request as draft November 5, 2024 00:04

@JsonProperty("position")
Copy link

Choose a reason for hiding this comment

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

Is position an invalid property on a Circle Asn1Object in all cases, or is there any scenario where we want to have position present? I'm gathering that, at minimum, we don't want both position and center present, but is there a scenario where we could want position present when center is not (and vice versa)?

Comment on lines 290 to 315
ServiceRequest request = odeTID.getRequest();
request.setOde(new ServiceRequest.OdeInternal());
request.getOde().setVerb(ServiceRequest.OdeInternal.RequestVerb.PUT);
OdeTravelerInformationMessage tim = odeTID.getTim();
OdeMsgPayload timDataPayload = new OdeMsgPayload(tim);
OdeRequestMsgMetadata timMetadata = new OdeRequestMsgMetadata(timDataPayload, request);
timMetadata.setOdePacketID(tim.getPacketID());
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
int maxDurationTime = 0;
Date latestStartDateTime = null;
for (OdeTravelerInformationMessage.DataFrame dataFrameItem : tim.getDataframes()) {
maxDurationTime = Math.max(maxDurationTime, dataFrameItem.getDurationTime());
latestStartDateTime = latestStartDateTime == null || latestStartDateTime.before(dateFormat.parse(dataFrameItem.getStartDateTime()))
? dateFormat.parse(dataFrameItem.getStartDateTime())
: latestStartDateTime;
}
timMetadata.setMaxDurationTime(maxDurationTime);
timMetadata.setOdeTimStartDateTime(dateFormat.format(latestStartDateTime));
SerialId serialId = new SerialId();
serialId.setStreamId("testStreamId");
timMetadata.setSerialId(serialId);
timMetadata.setRecordGeneratedBy(OdeMsgMetadata.GeneratedBy.TMC);
timMetadata.setRecordGeneratedAt(DateTimeUtils.isoDateTime(DateTimeUtils.isoDateTime(tim.getTimeStamp())));
ObjectNode encodableTid = JsonUtils.toObjectNode(odeTID.toJson());
TravelerMessageFromHumanToAsnConverter.convertTravelerInputDataToEncodableTim(encodableTid);
timMetadata.setSchemaVersion(OdeProperties.OUTPUT_SCHEMA_VERSION);
Copy link

Choose a reason for hiding this comment

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

suggestion: it looks like this code block is pulled from the depositTim method. I'm fine with pulling the logic out and duplicating it for this test, since the depositTim method is a Big Ball O' Mud ™️. It might be helpful for future maintainers if you added a comment explaining where this logic comes from and why it's necessary.

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've added a method-level comment explaining where the logic comes from and why it was pulled.

String actualXML = TimTransmogrifier.convertToXml(null, encodableTid, timMetadata, serialId);

// verify
actualXML = actualXML.replaceFirst("<odeReceivedAt>.*</odeReceivedAt>", "<odeReceivedAt>2024-11-05T16:51:14.473Z</odeReceivedAt>"); // replace <odeReceivedAt> with a fixed value for comparison
Copy link

Choose a reason for hiding this comment

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

suggestion(non-blocking): If we're editing the actual value, we're not truly testing that the code produces a specific output. It's not a huge deal to me since the rest of this code mocks the time value with an invalid timestamp🤢 instead. I like your solution here better than that, but I'd suggest looking at where the time value is provided and finding a way to use a static/fixed clock instead of rewriting the return value. I'm doing something like that over in my other PR, so feel free to copy that pattern, but it may be worth your time to consider a better approach.

@dmccoystephenson dmccoystephenson marked this pull request as ready for review November 5, 2024 19:12
Copy link
Collaborator

@drewjj drewjj left a comment

Choose a reason for hiding this comment

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

This makes sense to me

Copy link

@Michael7371 Michael7371 left a comment

Choose a reason for hiding this comment

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

Looks good!

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.

4 participants