use of cern.modesti.schema.field.Field in project modesti by jlsalmon.
the class SchemaInitialiser method loadSchemas.
/**
* Load all schemas inside plugins.
*
* @return the list of schemas that were found on the classpath
* @throws IOException
* @throws URISyntaxException
*/
private List<SchemaImpl> loadSchemas() throws IOException, URISyntaxException {
List<SchemaImpl> schemas = new ArrayList<>();
Map<String, List<SchemaImpl>> pluginSchemas = loadPluginSchemas();
Map<String, List<CategoryImpl>> pluginCategories = loadPluginCategories();
Map<String, List<DatasourceImpl>> pluginDatasources = loadPluginDatasources();
for (Map.Entry<String, List<SchemaImpl>> entry : pluginSchemas.entrySet()) {
for (SchemaImpl schema : entry.getValue()) {
List<Category> categories = new ArrayList<>();
List<Datasource> datasources = new ArrayList<>();
// Skip over abstract schemas
if (schema.isAbstract()) {
continue;
}
// Merge in the parent schema if it is specified
String parent = schema.getParent();
if (parent != null) {
Schema parentSchema = getSchema(pluginSchemas, parent);
if (parentSchema == null) {
throw new IllegalArgumentException(format("Schema %s extends from unknown parent schema %s", schema.getId(), parent));
}
categories.addAll(parentSchema.getCategories());
datasources.addAll(parentSchema.getDatasources());
schema.setIdProperty(parentSchema.getIdProperty());
schema.setSelectableStates(parentSchema.getSelectableStates());
schema.setRowCommentStates(parentSchema.getRowCommentStates());
}
// Attach categories that are specified in the schema
for (Category category : schema.getCategories()) {
boolean categoryFound = false;
for (Map.Entry<String, List<CategoryImpl>> categoryEntry : pluginCategories.entrySet()) {
if (categoryEntry.getValue().contains(category)) {
categories.add(categoryEntry.getValue().get(categoryEntry.getValue().indexOf(category)));
categoryFound = true;
}
}
if (!categoryFound) {
throw new IllegalArgumentException(format("Category %s was not found for schema %s", category.getId(), schema.getId()));
}
// TODO: support referencing another field by name to avoid duplicate field definitions
}
// Attach datasources that are specified in the schema
for (Datasource datasource : schema.getDatasources()) {
boolean datasourceFound = false;
for (Map.Entry<String, List<DatasourceImpl>> datasourceEntry : pluginDatasources.entrySet()) {
if (datasourceEntry.getValue().contains(datasource)) {
datasources.add(datasourceEntry.getValue().get(datasourceEntry.getValue().indexOf(datasource)));
datasourceFound = true;
}
}
if (!datasourceFound) {
throw new IllegalArgumentException(format("Datasource %s was not found for schema %s", datasource.getId(), schema.getId()));
}
}
// Process any overrides to the core categories
for (Category override : schema.getOverrides()) {
if (categories.contains(override)) {
Category overridden = mergeCategories(categories.get(categories.indexOf(override)), override);
categories.set(categories.indexOf(override), overridden);
}
}
// Process any overrides to the core datasources
for (Datasource override : schema.getDatasourceOverrides()) {
if (datasources.contains(override)) {
Category overridden = mergeCategories(datasources.get(datasources.indexOf(override)), override);
datasources.set(datasources.indexOf(override), new DatasourceImpl((DatasourceImpl) overridden));
}
}
schema.setCategories(categories);
schema.setDatasources(datasources);
// Invoke any post processors
Map<String, SchemaPostProcessor> postProcessors = applicationContext.getBeansOfType(SchemaPostProcessor.class);
for (SchemaPostProcessor postProcessor : postProcessors.values()) {
schema = (SchemaImpl) postProcessor.postProcess(schema);
}
schemas.add(schema);
}
}
String loadedPlugIns = schemas.stream().map(p -> p.getId()).collect(Collectors.joining(", "));
log.trace("loaded {} schemas [{}]", schemas.size(), loadedPlugIns);
return schemas;
}
use of cern.modesti.schema.field.Field in project modesti by jlsalmon.
the class Constraints method validateXnorConstraint.
private static boolean validateXnorConstraint(Constraint constraint, Request request, Category category) {
boolean valid = true;
for (Point point : request.getNonEmptyPoints()) {
// Constraints are only applied if the category is editable.
boolean editable = Conditionals.evaluate(category.getEditable(), point, request);
if (!editable) {
continue;
}
// Get all the fields specified as members of the constraint
List<Field> fields = category.getFields(constraint.getMembers());
// Get a list of fields for the constraint that are empty
List<Field> emptyFields = point.getEmptyFields(fields);
if (emptyFields.size() != 0 && emptyFields.size() != constraint.getMembers().size()) {
point.setValid(false);
valid = false;
for (Field emptyField : emptyFields) {
point.addErrorMessage(category.getId(), emptyField.getId(), "'" + emptyField.getName() + "' is required for group '" + category.getName() + "'");
}
}
}
return valid;
}
use of cern.modesti.schema.field.Field in project modesti by jlsalmon.
the class Constraints method validateAndConstraint.
private static boolean validateAndConstraint(Constraint constraint, Request request, Category category) {
boolean valid = true;
for (Point point : request.getNonEmptyPoints()) {
// Constraints are only applied if the category is editable.
boolean editable = Conditionals.evaluate(category.getEditable(), point, request);
if (!editable) {
continue;
}
// Get all the fields specified as members of the constraint
List<Field> fields = category.getFields(constraint.getMembers());
// Get a list of fields for the constraint that are empty
List<Field> emptyFields = point.getEmptyFields(fields);
if (emptyFields.size() > 0) {
point.setValid(false);
valid = false;
for (Field emptyField : emptyFields) {
point.addErrorMessage(category.getId(), emptyField.getId(), "'" + emptyField.getName() + "' is required for group '" + category.getName() + "'");
}
}
}
return valid;
}
use of cern.modesti.schema.field.Field in project modesti by jlsalmon.
the class Constraints method validateOrConstraint.
private static boolean validateOrConstraint(Constraint constraint, Request request, Category category) {
boolean valid = true;
for (Point point : request.getNonEmptyPoints()) {
// Constraints are only applied if the category is editable.
boolean editable = Conditionals.evaluate(category.getEditable(), point, request);
if (!editable) {
continue;
}
// Get all the fields specified as members of the constraint
List<Field> fields = category.getFields(constraint.getMembers());
// Get a list of fields for the constraint that are empty
List<Field> emptyFields = point.getEmptyFields(fields);
if (emptyFields.size() == constraint.getMembers().size()) {
point.setValid(false);
valid = false;
// TODO: set category to invalid
// point.properties.valid = category.valid = valid = false;
List<String> fieldNames = category.getFieldNames(constraint.getMembers());
for (Field emptyField : emptyFields) {
point.addErrorMessage(category.getId(), emptyField.getId(), "At least one of '" + String.join(", ", fieldNames) + "' is required for group '" + category.getName() + "'");
}
}
}
return valid;
}
use of cern.modesti.schema.field.Field in project modesti by jlsalmon.
the class CoreValidationService method validatePoints.
private boolean validatePoints(Request request, List<Category> categories) {
boolean valid = true;
for (Point point : request.getNonEmptyPoints()) {
for (Category category : categories) {
for (Field field : category.getFields()) {
Object value = point.getValueByPropertyName(field.getPropertyName());
// Check for invalid fields
if (!isValidValue(value, point, field)) {
point.setValid(false);
valid = false;
point.addErrorMessage(category.getId(), field.getId(), "Value '" + value + "' is not a legal option for field '" + field.getName() + "'. Please select a value from the list.");
}
// Validate unique fields
if (field.getUnique() != null) {
Constraint constraint = new Constraint("unique", Collections.singletonList(field.getId()), null);
if (!Constraints.validate(constraint, request, category)) {
valid = false;
}
}
// Required fields (can be simple boolean or condition list)
boolean required = false;
if (field.getRequired() instanceof Boolean && (Boolean) field.getRequired()) {
required = true;
} else if (field.getRequired() != null) {
required = Conditionals.evaluate(field.getRequired(), point, request);
}
if (required) {
if (value == null || value.equals("")) {
point.setValid(false);
valid = false;
point.addErrorMessage(category.getId(), field.getId(), "'" + field.getName() + "' is mandatory");
}
}
// Min length
if (field.getMinLength() != null) {
if (value != null && value.toString().length() < field.getMinLength()) {
point.setValid(false);
valid = false;
point.addErrorMessage(category.getId(), field.getId(), "'" + field.getName() + "' must be at least " + field.getMinLength() + " characters in length");
}
}
// Max length
if (field.getMaxLength() != null) {
if (value != null && value.toString().length() > field.getMaxLength()) {
point.setValid(false);
valid = false;
point.addErrorMessage(category.getId(), field.getId(), "'" + field.getName() + "' must not exceed " + field.getMaxLength() + " characters in length");
}
}
// Numeric fields
if (field.getType().equals("numeric")) {
if (value != null && !value.toString().isEmpty() && !NumberUtils.isNumber(value.toString())) {
point.setValid(false);
valid = false;
point.addErrorMessage(category.getId(), field.getId(), "Value for '" + field.getName() + "' must be numeric");
}
}
}
}
}
return valid;
}
Aggregations