Search in sources :

Example 1 with Field

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;
}
Also used : Datasource(cern.modesti.schema.category.Datasource) java.util(java.util) URISyntaxException(java.net.URISyntaxException) Autowired(org.springframework.beans.factory.annotation.Autowired) SerializationUtils(org.apache.commons.lang3.SerializationUtils) PathMatchingResourcePatternResolver(org.springframework.core.io.support.PathMatchingResourcePatternResolver) URLConnection(java.net.URLConnection) JarURLConnection(java.net.JarURLConnection) Resource(org.springframework.core.io.Resource) DatasourceImpl(cern.modesti.schema.category.DatasourceImpl) SchemaPostProcessor(cern.modesti.schema.spi.SchemaPostProcessor) ObjectMapper(com.fasterxml.jackson.databind.ObjectMapper) IOException(java.io.IOException) Datasource(cern.modesti.schema.category.Datasource) ApplicationContext(org.springframework.context.ApplicationContext) Collectors(java.util.stream.Collectors) File(java.io.File) StandardCharsets(java.nio.charset.StandardCharsets) String.format(java.lang.String.format) Slf4j(lombok.extern.slf4j.Slf4j) Component(org.springframework.stereotype.Component) Field(cern.modesti.schema.field.Field) ByteStreams(com.google.common.io.ByteStreams) PostConstruct(javax.annotation.PostConstruct) Category(cern.modesti.schema.category.Category) CategoryImpl(cern.modesti.schema.category.CategoryImpl) ResourcePatternResolver(org.springframework.core.io.support.ResourcePatternResolver) BeanUtils(org.springframework.beans.BeanUtils) Category(cern.modesti.schema.category.Category) SchemaPostProcessor(cern.modesti.schema.spi.SchemaPostProcessor) DatasourceImpl(cern.modesti.schema.category.DatasourceImpl)

Example 2 with Field

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;
}
Also used : Field(cern.modesti.schema.field.Field) Point(cern.modesti.point.Point)

Example 3 with Field

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;
}
Also used : Field(cern.modesti.schema.field.Field) Point(cern.modesti.point.Point)

Example 4 with Field

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;
}
Also used : Field(cern.modesti.schema.field.Field) Point(cern.modesti.point.Point)

Example 5 with Field

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;
}
Also used : AutocompleteField(cern.modesti.schema.field.AutocompleteField) Field(cern.modesti.schema.field.Field) OptionsField(cern.modesti.schema.field.OptionsField) Category(cern.modesti.schema.category.Category) Constraint(cern.modesti.schema.category.Constraint) Point(cern.modesti.point.Point)

Aggregations

Field (cern.modesti.schema.field.Field)8 Point (cern.modesti.point.Point)5 Category (cern.modesti.schema.category.Category)3 CategoryImpl (cern.modesti.schema.category.CategoryImpl)2 AutocompleteField (cern.modesti.schema.field.AutocompleteField)2 OptionsField (cern.modesti.schema.field.OptionsField)2 Constraint (cern.modesti.schema.category.Constraint)1 Datasource (cern.modesti.schema.category.Datasource)1 DatasourceImpl (cern.modesti.schema.category.DatasourceImpl)1 SchemaPostProcessor (cern.modesti.schema.spi.SchemaPostProcessor)1 ObjectMapper (com.fasterxml.jackson.databind.ObjectMapper)1 ByteStreams (com.google.common.io.ByteStreams)1 File (java.io.File)1 IOException (java.io.IOException)1 String.format (java.lang.String.format)1 JarURLConnection (java.net.JarURLConnection)1 URISyntaxException (java.net.URISyntaxException)1 URLConnection (java.net.URLConnection)1 StandardCharsets (java.nio.charset.StandardCharsets)1 java.util (java.util)1