use of org.batfish.datamodel.questions.Question.InstanceData.Variable in project batfish by batfish.
the class Question method preprocessQuestion.
private static String preprocessQuestion(String rawQuestionText) {
try {
JSONObject jobj = new JSONObject(rawQuestionText);
if (jobj.has(BfConsts.PROP_INSTANCE) && !jobj.isNull(BfConsts.PROP_INSTANCE)) {
String instanceDataStr = jobj.getString(BfConsts.PROP_INSTANCE);
InstanceData instanceData = BatfishObjectMapper.mapper().readValue(instanceDataStr, new TypeReference<InstanceData>() {
});
for (Entry<String, Variable> e : instanceData.getVariables().entrySet()) {
String varName = e.getKey();
Variable variable = e.getValue();
JsonNode value = variable.getValue();
if (value == null) {
if (variable.getOptional()) {
/*
* Recursively look for all key, value pairs and remove keys
* whose value is "${varName}." Is this fragile?
* To be doubly sure, we do only for keys whole parent object is a questions, which
* we judge by it having a key "class" whose value starts with "org.batfish.question"
*/
recursivelyRemoveOptionalVar(jobj, varName);
} else {
// What to do here? For now, do nothing and assume that
// later validation will handle it.
}
continue;
}
if (variable.getType() == Variable.Type.QUESTION) {
if (variable.getMinElements() != null) {
if (!value.isArray()) {
throw new IllegalArgumentException("Expecting JSON array for array type");
}
JSONArray arr = new JSONArray();
for (int i = 0; i < value.size(); i++) {
String valueJsonString = new ObjectMapper().writeValueAsString(value.get(i));
arr.put(i, new JSONObject(preprocessQuestion(valueJsonString)));
}
jobj.put(varName, arr);
} else {
String valueJsonString = new ObjectMapper().writeValueAsString(value);
jobj.put(varName, new JSONObject(preprocessQuestion(valueJsonString)));
}
}
}
String questionText = jobj.toString();
for (Entry<String, Variable> e : instanceData.getVariables().entrySet()) {
String varName = e.getKey();
Variable variable = e.getValue();
JsonNode value = variable.getValue();
String valueJsonString = new ObjectMapper().writeValueAsString(value);
boolean stringType = variable.getType().getStringType();
boolean setType = variable.getMinElements() != null;
if (value != null) {
String topLevelVarNameRegex = Pattern.quote("\"${" + varName + "}\"");
String inlineVarNameRegex = Pattern.quote("${" + varName + "}");
String topLevelReplacement = valueJsonString;
String inlineReplacement;
if (stringType && !setType) {
inlineReplacement = valueJsonString.substring(1, valueJsonString.length() - 1);
} else {
String quotedValueJsonString = JSONObject.quote(valueJsonString);
inlineReplacement = quotedValueJsonString.substring(1, quotedValueJsonString.length() - 1);
}
String inlineReplacementRegex = Matcher.quoteReplacement(inlineReplacement);
String topLevelReplacementRegex = Matcher.quoteReplacement(topLevelReplacement);
questionText = questionText.replaceAll(topLevelVarNameRegex, topLevelReplacementRegex);
questionText = questionText.replaceAll(inlineVarNameRegex, inlineReplacementRegex);
}
}
return questionText;
}
return rawQuestionText;
} catch (JSONException | IOException e) {
throw new BatfishException(String.format("Could not convert raw question text [%s] to JSON", rawQuestionText), e);
}
}
use of org.batfish.datamodel.questions.Question.InstanceData.Variable in project batfish by batfish.
the class Client method checkVariableState.
/**
* Verify that every non-optional variable has value assigned to it.
*
* @throws BatfishException when there exists a missing parameter: it is not optional in {@code
* variable}, but the user failed to provide it.
*/
static void checkVariableState(Map<String, Variable> variables) throws BatfishException {
for (Entry<String, Variable> e : variables.entrySet()) {
String variableName = e.getKey();
Variable variable = e.getValue();
if (!variable.getOptional() && variable.getValue() == null) {
throw new BatfishException(String.format("Missing parameter: %s", variableName));
}
}
}
use of org.batfish.datamodel.questions.Question.InstanceData.Variable in project batfish by batfish.
the class Client method validateAndSet.
/**
* For each key in {@code parameters}, validate that its value satisfies the requirements
* specified by {@code variables} for that specific key. Set value to {@code variables} if
* validation passed.
*
* @throws BatfishException if the key in parameters does not exist in variable, or the values in
* {@code parameters} do not match the requirements in {@code variables} for that specific
* key.
*/
static void validateAndSet(Map<String, JsonNode> parameters, Map<String, Variable> variables) throws BatfishException {
for (Entry<String, JsonNode> e : parameters.entrySet()) {
String parameterName = e.getKey();
JsonNode value = e.getValue();
Variable variable = variables.get(parameterName);
if (variable == null) {
throw new BatfishException("No variable named: '" + parameterName + "' in supplied question template");
}
if (variable.getMinElements() != null) {
// Value is an array, check size and validate each elements in it
if (!value.isArray() || value.size() < variable.getMinElements()) {
throw new BatfishException(String.format("Invalid value for parameter %s: %s. " + "Expecting a JSON array of at least %d " + "elements", parameterName, value, variable.getMinElements()));
}
for (JsonNode node : value) {
validateNode(node, variable, parameterName);
}
} else {
validateNode(value, variable, parameterName);
}
// validation passed.
variable.setValue(value);
}
}
use of org.batfish.datamodel.questions.Question.InstanceData.Variable in project batfish by batfish.
the class ClientTest method testSatisfiedMinLengthValue.
@Test
public void testSatisfiedMinLengthValue() throws IOException {
String longString = "\"long enough\"";
Question.InstanceData.Variable variable = new Question.InstanceData.Variable();
variable.setMinLength(8);
variable.setType(STRING);
Client.validateType(_mapper.readTree(longString), variable);
}
use of org.batfish.datamodel.questions.Question.InstanceData.Variable in project batfish by batfish.
the class ClientTest method testValidateValidNode.
@Test
public void testValidateValidNode() throws IOException {
String parameterName = "boolean";
JsonNode invalidNode = _mapper.readTree("false");
Question.InstanceData.Variable variable = new Question.InstanceData.Variable();
variable.setType(BOOLEAN);
SortedSet<String> allowedValues = new TreeSet<>();
allowedValues.add("false");
variable.setAllowedValues(allowedValues);
Client.validateNode(invalidNode, variable, parameterName);
}
Aggregations