Skip to content

Commit

Permalink
Added various precondition tests for the init() method of the person …
Browse files Browse the repository at this point in the history
…property data manager and fixed an edge case that allowed the simulation to run when there was a property with no default value and there were no covering values assigned for any person in the population. (#269)
  • Loading branch information
shawnhatch authored Oct 30, 2024
1 parent 92484b5 commit 879f87d
Show file tree
Hide file tree
Showing 2 changed files with 314 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -492,7 +492,7 @@ public double getPersonPropertyTime(final PersonId personId, final PersonPropert
validatePersonPropertyId(personPropertyId);
validatePersonPropertyAssignmentTimesTracked(personPropertyId);
DoubleValueContainer doubleValueContainer = propertyTimes.get(personPropertyId);
if(doubleValueContainer == null) {
if (doubleValueContainer == null) {
return propertyDefinitionTimes.get(personPropertyId);
}
return doubleValueContainer.getValue(personId.getValue());
Expand Down Expand Up @@ -770,6 +770,12 @@ private void loadPropertyValues() {
*
* 4) person does not exist, property value is not present -- nothing to do
*/

/*
* To preserve the ordering necessary for run continuity, we only process the
* property ids contained in the plugin data's stored person property values. We
* show that properties that do not have defaults are properly tested below.
*/
Map<PersonPropertyId, List<Object>> map = personPropertiesPluginData.getPropertyValues();
for (PersonPropertyId personPropertyId : map.keySet()) {
List<Object> list = map.get(personPropertyId);
Expand Down Expand Up @@ -806,6 +812,25 @@ private void loadPropertyValues() {
}
}

/*
* If there are any people, we need to determine if there were any property
* definitions that do not have default values and were excluded from the stored
* person property values in the plugin data.
*/
if (peopleDataManager.getPopulationCount() > 0) {
Set<PersonPropertyId> potentiallyInsufficientPropertyIds = new LinkedHashSet<>();
potentiallyInsufficientPropertyIds.addAll(propertyDefinitions.keySet());
potentiallyInsufficientPropertyIds.removeAll(map.keySet());

for (PersonPropertyId personPropertyId : potentiallyInsufficientPropertyIds) {
PropertyDefinition propertyDefinition = propertyDefinitions.get(personPropertyId);
boolean defaultIsPresent = propertyDefinition.getDefaultValue().isPresent();
if (!defaultIsPresent) {
throw new ContractException(PropertyError.INSUFFICIENT_PROPERTY_VALUE_ASSIGNMENT, personPropertyId);
}
}

}
}

private void loadPropertyTimes() {
Expand Down Expand Up @@ -858,6 +883,32 @@ private void loadPropertyTimes() {
}
}

/**
* Inititalizes the data manager by loading its state from the plugin data.
*
* @throws ContractException
* <ul>
* <li>{@linkplain PersonPropertyError#PROPERTY_DEFAULT_TIME_EXCEEDS_SIM_TIME}
* if the default time of a property exceeds that
* start time of the simulation</li>
* <li>{@linkplain PropertyError#INSUFFICIENT_PROPERTY_VALUE_ASSIGNMENT}
* if a property value for a person is not present for
* a property whose definition does not have a default
* value</li>
* <li>{@linkplain PersonPropertyError#UNKNOWN_PERSON_HAS_PROPERTY_VALUE_ASSIGNMENT}
* if a property value was collected for an unknown
* person -- i.e. not defined in the people plugin
* data</li>
* <li>{@linkplain PersonPropertyError#PROPERTY_ASSIGNMENT_TIME_EXCEEDS_SIM_TIME}
* if a property assignment time for a person exceeds
* the simulation start time and thus is happening in
* the future</li>
* <li>{@linkplain PersonPropertyError#UNKNOWN_PERSON_HAS_PROPERTY_ASSIGNMENT_TIME}
* if a person property value has been collected for
* an unknown person</li>
*
* </ul>
*/
@Override
public void init(DataManagerContext dataManagerContext) {
super.init(dataManagerContext);
Expand Down
Loading

0 comments on commit 879f87d

Please sign in to comment.