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

move dimension data to gcm #210

Merged
merged 1 commit into from
Feb 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package gov.hhs.aspr.ms.gcm.nucleus;

import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import gov.hhs.aspr.ms.util.errors.ContractException;

public abstract class DimensionData {
protected final List<String> levelNames;
private final Map<String, Integer> levelNameToLevelMap = new LinkedHashMap<>();
protected final int levelCount;

/**
* The passed in list of levelNames is assumed to be a list of unique names. This constructor does NO validation. It is up to the class implementing this class to do the validation beforehand.
*/
protected DimensionData(List<String> levelNames) {
this.levelCount = levelNames.size();

int counter = 0;
for(String levelName : levelNames) {
this.levelNameToLevelMap.put(levelName, counter++);
}

this.levelNames = new ArrayList<>(levelNames);
}

/**
* returns the number of levels
*/
public final int getLevelCount() {
return this.levelCount;
}

/**
* returns the level name for the given int level
*
* @throws ContractException
* <ul>
* <li>{@linkplain NucleusError#INVALID_DIMENSION_LEVEL}
* if the int level is less than 0 or greater than the
* number of levels</li>
* </ul>
*/
public final String getLevelName(int level) {
if (level < 0 || level > this.getLevelCount()) {
throw new ContractException(NucleusError.INVALID_DIMENSION_LEVEL, level);
}

return this.levelNames.get(level);
}

/**
* returns the list of level names
*/
public final List<String> getLevelNames() {
return Collections.unmodifiableList(levelNames);
}

/**
* returns the int level associated with the given levelName
*
* @throws ContractException
* <ul>
* <li>{@linkplain NucleusError#UNKNOWN_DIMENSION_LEVEL_NAME}
* if the levelName does not exist</li>
* </ul>
*/
public final int getLevel(String levelName) {
Integer level = this.levelNameToLevelMap.get(levelName);

if (level != null) {
return level.intValue();
}

throw new ContractException(NucleusError.UNKNOWN_DIMENSION_LEVEL_NAME, levelName);
}

public abstract int hashCode();

public abstract boolean equals(Object obj);

public abstract String toString();
}
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,9 @@ public enum NucleusError implements ContractError {
UNKNOWN_FUNCTION_ID("Unknown event function id"), NULL_FUNCTION_ID("Null function id"),
NULL_FUNCTION_VALUE("Null event function value"), NULL_FUNCTION("Null function"),
NULL_IDENTIFIABLE_FUNCTION("Null identifiable function"), NULL_EVENT_FILTER("Null event filter"),
INVALID_PLAN_ARRIVAL_ID("The given plan id is invalid. It either needs to be >=0, or -1, and nothing else"),;
INVALID_PLAN_ARRIVAL_ID("The given plan id is invalid. It either needs to be >=0, or -1, and nothing else"),
INVALID_DIMENSION_LEVEL("Invalid Dimension Level"),
UNKNOWN_DIMENSION_LEVEL_NAME("The given level name is not known"),;

private final String description;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,289 @@
package gov.hhs.aspr.ms.gcm.nucleus;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

import org.apache.commons.math3.random.RandomGenerator;
import org.junit.jupiter.api.Test;

import gov.hhs.aspr.ms.util.annotations.UnitTestMethod;
import gov.hhs.aspr.ms.util.errors.ContractException;
import gov.hhs.aspr.ms.util.random.RandomGeneratorProvider;

public class AT_DimensionData {

private static class TestDimensionData extends DimensionData {

private static class Data {
private final List<String> levelNames = new ArrayList<>();

private boolean locked;

private Data() {
}

private Data(Data data) {
levelNames.addAll(data.levelNames);
}

@Override
public int hashCode() {
return Objects.hash(levelNames);
}

@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}

if (!(obj instanceof Data)) {
return false;
}

Data other = (Data) obj;

return Objects.equals(levelNames, other.levelNames);
}

@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("Data [");
builder.append("levelNames=");
builder.append(levelNames);
builder.append("]");
return builder.toString();
}

}

private static class Builder {
private Data data;

private Builder(Data data) {
this.data = data;
}

public Builder addLevel(String levelName) {
ensureDataMutability();
this.data.levelNames.add(levelName);

return this;
}

public TestDimensionData build() {
if (!data.locked) {
validateData();
}
ensureImmutability();
return new TestDimensionData(data);
}

private void ensureDataMutability() {
if (data.locked) {
data = new Data(data);
data.locked = false;
}
}

private void ensureImmutability() {
if (!data.locked) {
data.locked = true;
}
}

private void validateData() {

}

}

public static Builder builder() {
return new Builder(new Data());
}

private final Data data;

protected TestDimensionData(Data data) {
super(data.levelNames);
this.data = data;
}

@Override
public int hashCode() {
return Objects.hash(data);
}

@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof TestDimensionData)) {
return false;
}
TestDimensionData other = (TestDimensionData) obj;
return Objects.equals(data, other.data);
}

@Override
public String toString() {
return "TestDimensionData [data=" + data + "]";
}
}

@Test
@UnitTestMethod(target = DimensionData.class, name = "getLevelCount", args = {})
public void testGetLevelCount() {
RandomGenerator randomGenerator = RandomGeneratorProvider.getRandomGenerator(3226863657242118228L);

for (int i = 0; i < 10; i++) {
int expectedLevelCount = randomGenerator.nextInt(100);
TestDimensionData.Builder builder = TestDimensionData.builder();

for (int j = 0; j < expectedLevelCount; j++) {
builder.addLevel(Integer.toString(j));
}

TestDimensionData dimensionData = builder.build();

assertEquals(expectedLevelCount, dimensionData.getLevelCount());
}
}

@Test
@UnitTestMethod(target = DimensionData.class, name = "getLevelName", args = { int.class })
public void testGetLevelName() {
RandomGenerator randomGenerator = RandomGeneratorProvider.getRandomGenerator(612509749724622534L);

for (int i = 0; i < 10; i++) {
int levelCount = randomGenerator.nextInt(100);
TestDimensionData.Builder builder = TestDimensionData.builder();

for (int j = 0; j < levelCount; j++) {
builder.addLevel(Integer.toString(j));
}

for (int j = 0; j < levelCount; j++) {
builder.addLevel(Integer.toString(j + 100));
}

for (int j = 0; j < levelCount; j++) {
builder.addLevel(Integer.toString(j + 1000));
}

TestDimensionData dimensionData = builder.build();

for (int j = 0; j < levelCount; j++) {
assertNotNull(dimensionData.getLevelName(j));
assertNotNull(dimensionData.getLevelName(levelCount + j));
assertNotNull(dimensionData.getLevelName(levelCount * 2 + j));

assertEquals(Integer.toString(j), dimensionData.getLevelName(j));
assertEquals(Integer.toString(j + 100), dimensionData.getLevelName(levelCount + j));
assertEquals(Integer.toString(j + 1000), dimensionData.getLevelName(levelCount * 2 + j));
}
}

// preconditions
// level is < 0
ContractException contractException = assertThrows(ContractException.class, () -> {
TestDimensionData dimensionData = TestDimensionData.builder().build();
dimensionData.getLevelName(-1);
});

assertEquals(NucleusError.INVALID_DIMENSION_LEVEL, contractException.getErrorType());

// level is > level count
contractException = assertThrows(ContractException.class, () -> {
TestDimensionData dimensionData = TestDimensionData.builder().build();
dimensionData.getLevelName(1);
});

assertEquals(NucleusError.INVALID_DIMENSION_LEVEL, contractException.getErrorType());
}

@Test
@UnitTestMethod(target = DimensionData.class, name = "getLevelNames", args = {})
public void testGetLevelNames() {
RandomGenerator randomGenerator = RandomGeneratorProvider.getRandomGenerator(612509749724622534L);

for (int i = 0; i < 10; i++) {
int levelCount = randomGenerator.nextInt(100);
List<String> expectedLevelNames = new ArrayList<>();
TestDimensionData.Builder builder = TestDimensionData.builder();

for (int j = 0; j < levelCount; j++) {
builder.addLevel(Integer.toString(j));
expectedLevelNames.add(Integer.toString(j));
}

for (int j = 0; j < levelCount; j++) {
builder.addLevel(Integer.toString(j + 100));
expectedLevelNames.add(Integer.toString(j + 100));
}

for (int j = 0; j < levelCount; j++) {
builder.addLevel(Integer.toString(j + 1000));
expectedLevelNames.add(Integer.toString(j + 1000));
}

TestDimensionData dimensionData = builder.build();
List<String> actualLevelNames = dimensionData.getLevelNames();

assertEquals(expectedLevelNames.size(), actualLevelNames.size());
assertEquals(expectedLevelNames, actualLevelNames);

for (int j = 0; j < expectedLevelNames.size(); j++) {
assertEquals(expectedLevelNames.get(j), actualLevelNames.get(j));
}
}
}

@Test
@UnitTestMethod(target = DimensionData.class, name = "getLevel", args = { String.class })
public void testGetLevel() {
RandomGenerator randomGenerator = RandomGeneratorProvider.getRandomGenerator(612509749724622534L);

for (int i = 0; i < 10; i++) {
int levelCount = randomGenerator.nextInt(100);
TestDimensionData.Builder builder = TestDimensionData.builder();

for (int j = 0; j < levelCount; j++) {
builder.addLevel(Integer.toString(j));
}

for (int j = 0; j < levelCount; j++) {
builder.addLevel(Integer.toString(j + 100));
}

for (int j = 0; j < levelCount; j++) {

builder.addLevel(Integer.toString(j + 1000));
}

TestDimensionData dimensionData = builder.build();

for (int j = 0; j < levelCount; j++) {
assertEquals(j, dimensionData.getLevel(Integer.toString(j)));
assertEquals(levelCount + j, dimensionData.getLevel(Integer.toString(j + 100)));
assertEquals(levelCount * 2 + j, dimensionData.getLevel(Integer.toString(j + 1000)));
}
}

// preconditions
// level name is unknown
ContractException contractException = assertThrows(ContractException.class, () -> {
TestDimensionData dimensionData = TestDimensionData.builder().build();
dimensionData.getLevel("BAD_LEVEL_NAME");
});

assertEquals(NucleusError.UNKNOWN_DIMENSION_LEVEL_NAME, contractException.getErrorType());
}
}