-
Notifications
You must be signed in to change notification settings - Fork 21
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 @AllChildren annotation #1367
base: develop
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -46,6 +46,7 @@ | |
import javax.lang.model.util.Types; | ||
import javax.tools.Diagnostic; | ||
import java.time.Instant; | ||
import java.util.Arrays; | ||
import java.util.HashMap; | ||
import java.util.List; | ||
import java.util.Map; | ||
|
@@ -265,7 +266,7 @@ public JavaFile generateSchedulerModel(final MissionModelRecord missionModel) { | |
.classBuilder(typeName) | ||
.addAnnotation( | ||
AnnotationSpec | ||
.builder(javax.annotation.processing.Generated.class) | ||
.builder(Generated.class) | ||
.addMember("value", "$S", MissionModelProcessor.class.getCanonicalName()) | ||
.build()) | ||
.addModifiers(Modifier.PUBLIC, Modifier.FINAL) | ||
|
@@ -327,6 +328,23 @@ public JavaFile generateSchedulerModel(final MissionModelRecord missionModel) { | |
) | ||
.returns(Duration.class) | ||
.build()) | ||
.addMethod(MethodSpec | ||
.methodBuilder("getChildren") | ||
.addModifiers(Modifier.PUBLIC) | ||
.addAnnotation(Override.class) | ||
.returns(ParameterizedTypeName.get(ClassName.get(Map.class), ClassName.get(String.class), ParameterizedTypeName.get(List.class, String.class))) | ||
.addStatement("final var result = new $T()", ParameterizedTypeName.get(ClassName.get(HashMap.class), ClassName.get(String.class), ParameterizedTypeName.get(List.class, String.class))) | ||
.addCode( | ||
missionModel | ||
.activityTypes() | ||
.stream() | ||
.map( | ||
activityTypeRecord -> | ||
getChildrenStatement(missionModel, activityTypeRecord)) | ||
.reduce((x, y) -> x.add("$L", y.build())) | ||
.orElse(CodeBlock.builder()).build()) | ||
.addStatement("return result") | ||
.build()) | ||
|
||
.build(); | ||
|
||
|
@@ -336,6 +354,26 @@ public JavaFile generateSchedulerModel(final MissionModelRecord missionModel) { | |
.build(); | ||
} | ||
|
||
private CodeBlock.Builder getChildrenStatement(final MissionModelRecord missionModel, final ActivityTypeRecord activityTypeRecord){ | ||
String[] children = null; | ||
//if the effect model is empty, an activity cannot have children | ||
if(activityTypeRecord.effectModel().isEmpty()) children = new String[]{}; | ||
else if(activityTypeRecord.effectModel().get().children().isPresent()){ | ||
//if children have been declared with an annotation, record those | ||
children = activityTypeRecord.effectModel().get().children().get(); | ||
} else { | ||
//if children have not been declared with an annotation, assume the activity might generate all activity types | ||
children = missionModel.activityTypes().stream().map(ActivityTypeRecord::name).toArray(String[]::new); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Memory-wise, rather than returning a list of every activity in the plan, what about wrapping the return in |
||
} | ||
final var childrenString = String.join(",", Arrays.stream(children).map(child-> "\""+child + "\"").toList()); | ||
|
||
return CodeBlock | ||
.builder() | ||
.addStatement("result.put(\"$L\", $L)", | ||
activityTypeRecord.name(), | ||
CodeBlock.of("$T.of($N)", List.class, childrenString)); | ||
} | ||
|
||
/** Generate `ActivityActions` class. */ | ||
public JavaFile generateActivityActions(final MissionModelRecord missionModel) { | ||
final var typeName = missionModel.getActivityActionsName(); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,10 +4,12 @@ | |
import gov.nasa.jpl.aerie.merlin.protocol.types.DurationType; | ||
import gov.nasa.jpl.aerie.merlin.protocol.types.SerializedValue; | ||
|
||
import java.util.List; | ||
import java.util.Map; | ||
|
||
public interface SchedulerModel { | ||
Map<String, DurationType> getDurationTypes(); | ||
SerializedValue serializeDuration(final Duration duration); | ||
Duration deserializeDuration(final SerializedValue serializedValue); | ||
Map<String, List<String>> getChildren(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Minor: If the data is provided in an array, what is gained by converting it into a List? Are there some List-only methods you expect the scheduler to use? Was it simpler to return a List in the code generator? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe this change makes this PR |
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package gov.nasa.jpl.aerie.scheduler; | ||
|
||
import org.junit.jupiter.api.Test; | ||
|
||
import java.util.HashSet; | ||
import java.util.List; | ||
|
||
import static org.junit.jupiter.api.Assertions.assertEquals; | ||
import static org.junit.jupiter.api.Assertions.assertTrue; | ||
|
||
public class AllChildrenTest { | ||
@Test | ||
public void testAllChildrenAnnotation(){ | ||
final var bananaSchedulerModel = SimulationUtility.getBananaSchedulerModel(); | ||
final var children = bananaSchedulerModel.getChildren(); | ||
final var bananaMissionModel = SimulationUtility.getBananaMissionModel(); | ||
final var allActivityTypes = bananaMissionModel.getDirectiveTypes().directiveTypes().keySet(); | ||
//there is one key per activity type in the children map | ||
allActivityTypes.forEach(at -> assertTrue(children.containsKey(at))); | ||
//the only declared child of parent is the one present in the children map | ||
assertEquals(List.of("child"), children.get("parent")); | ||
//the declared absence of children of grandchild is reported in the children map | ||
assertEquals(List.of(), children.get("grandchild")); | ||
//an activity without effect model does not have any children | ||
assertEquals(List.of(), children.get("ParameterTest")); | ||
//an activity with an effect model but with no @AllChildren annotation will result in all activity types of the mission model being reported as its potential children | ||
assertEquals(new HashSet<>(allActivityTypes.stream().toList()), new HashSet<>(children.get("BiteBanana"))); | ||
} | ||
} |
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.
Minor, nonblocking: this method could return an immutable map if it uses the
Map.ofEntries()
method.Then instead of each
getChildrenStatement
returningresult.put("TYPE", LIST)
, it would returnMap.entry("TYPE", LIST)
.