All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.atlasmap.core.BaseModuleValidationService Maven / Gradle / Ivy

/**
 * Copyright (C) 2017 Red Hat, Inc.
 * 

* Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at *

* http://www.apache.org/licenses/LICENSE-2.0 *

* Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package io.atlasmap.core; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Optional; import io.atlasmap.api.AtlasConversionService; import io.atlasmap.api.AtlasConverter; import io.atlasmap.api.AtlasValidationService; import io.atlasmap.spi.AtlasConversionConcern; import io.atlasmap.spi.AtlasConversionInfo; import io.atlasmap.spi.AtlasModuleDetail; import io.atlasmap.spi.AtlasModuleMode; import io.atlasmap.v2.AtlasMapping; import io.atlasmap.v2.BaseMapping; import io.atlasmap.v2.DataSource; import io.atlasmap.v2.Field; import io.atlasmap.v2.FieldType; import io.atlasmap.v2.Mapping; import io.atlasmap.v2.MappingType; import io.atlasmap.v2.Validation; import io.atlasmap.v2.ValidationStatus; public abstract class BaseModuleValidationService implements AtlasValidationService { private AtlasConversionService conversionService; private AtlasModuleMode mode; public BaseModuleValidationService() { this.conversionService = DefaultAtlasConversionService.getInstance(); } public BaseModuleValidationService(AtlasConversionService conversionService) { this.conversionService = conversionService; } public void setMode(AtlasModuleMode mode) { this.mode = mode; } public AtlasModuleMode getMode() { return mode; } public enum FieldDirection { INPUT("Input"), OUTPUT("Output"); private String value; FieldDirection(String value) { this.value = value; } public String value() { return value; } } protected abstract AtlasModuleDetail getModuleDetail(); @Override public List validateMapping(AtlasMapping mapping) { List validations = new ArrayList(); if (getMode() == AtlasModuleMode.UNSET) { Validation validation = new Validation(); validation.setMessage(String.format( "No mode specified for %s/%s, skipping module validations", this.getModuleDetail().name(), this.getClass().getSimpleName())); } if (mapping != null && mapping.getMappings() != null && mapping.getMappings().getMapping() != null && !mapping.getMappings().getMapping().isEmpty()) { validateMappingEntries(mapping.getMappings().getMapping(), validations); } boolean found = false; for (DataSource ds : mapping.getDataSource()) { if (ds.getUri() != null && ds.getUri().startsWith(getModuleDetail().uri())) { found = true; } } if (!found) { Validation validation = new Validation(); validation.setField(String.format("DataSource.uri")); validation.setMessage(String.format("No DataSource with '%s' uri specified", getModuleDetail().uri())); validation.setStatus(ValidationStatus.ERROR); validations.add(validation); } return validations; } protected void validateMappingEntries(List mappings, List validations) { for (BaseMapping fieldMapping : mappings) { if (fieldMapping.getClass().isAssignableFrom(Mapping.class) && MappingType.MAP.equals(((Mapping) fieldMapping).getMappingType())) { validateMapMapping((Mapping) fieldMapping, validations); } else if (fieldMapping.getClass().isAssignableFrom(Mapping.class) && MappingType.SEPARATE.equals(((Mapping) fieldMapping).getMappingType())) { validateSeparateMapping((Mapping) fieldMapping, validations); } } } protected void validateMapMapping(Mapping mapping, List validations) { Field inputField = null; Field outField = null; if (mapping != null && mapping.getInputField() != null && mapping.getInputField().size() > 0) { inputField = mapping.getInputField().get(0); if (getMode() == AtlasModuleMode.SOURCE) { validateField(inputField, FieldDirection.INPUT, validations); } } if (mapping != null && mapping.getOutputField() != null && mapping.getOutputField().size() > 0) { outField = mapping.getOutputField().get(0); if (getMode() == AtlasModuleMode.TARGET) { validateField(outField, FieldDirection.OUTPUT, validations); } } if (inputField != null && outField != null && getMode() == AtlasModuleMode.SOURCE) { // FIXME Run only for SOURCE to avoid duplicate validation... // we should convert per module validations to plugin style validateSourceAndTargetTypes(inputField, outField, validations); } } protected void validateSeparateMapping(Mapping mapping, List validations) { if (mapping == null) { return; } final Field inputField = mapping.getInputField() != null ? mapping.getInputField().get(0) : null; List outputFields =mapping.getOutputField(); if (getMode() == AtlasModuleMode.SOURCE) { // check that the input field is of type String else error if (inputField.getFieldType() != FieldType.STRING) { Validation validation = new Validation(); validation.setField("Input.Field"); validation.setMessage("Input field must be of type " + FieldType.STRING + " for a Separate Mapping"); validation.setStatus(ValidationStatus.ERROR); validation.setValue(getFieldName(inputField)); validations.add(validation); } validateField(inputField, FieldDirection.INPUT, validations); if (outputFields != null) { // FIXME Run only for SOURCE to avoid duplicate validation... // we should convert per module validations to plugin style for (Field outField : outputFields) { validateSourceAndTargetTypes(inputField, outField, validations); } } } else if (outputFields != null) { // TARGET outputFields.forEach(outField -> validateField(outField, FieldDirection.OUTPUT, validations)); } } protected void validateField(Field field, FieldDirection direction, List validations) { if (field == null || !getFieldType().isAssignableFrom(field.getClass())) { Validation validation = new Validation(); validation.setField(String.format("%s.Field", direction.value())); validation.setMessage(String.format("%s field %s is not supported by the %s", direction.value(), getFieldName(field), getModuleDetail().name())); validation.setStatus(ValidationStatus.ERROR); validations.add(validation); } else { validateModuleField((T)field, direction, validations); } } protected abstract Class getFieldType(); protected abstract void validateModuleField(T field, FieldDirection direction, List validation); protected void validateSourceAndTargetTypes(Field inputField, Field outField, List validations) { if (inputField.getFieldType() != outField.getFieldType()) { // is this check superseded by the further checks using the AtlasConversionInfo // annotations? // errors.getAllErrors().add(new AtlasMappingError("Field.Input/Output", // inputField.getType().value() + " --> " + outField.getType().value(), "Output // field type does not match input field type, may require a converter.", // AtlasMappingError.Level.WARN)); validateFieldTypeConversion(inputField, outField, validations); } } protected void populateConversionConcerns(AtlasConversionConcern[] atlasConversionConcerns, String value, List validations) { if (atlasConversionConcerns == null) { return; } for (AtlasConversionConcern atlasConversionConcern : atlasConversionConcerns) { if (AtlasConversionConcern.NONE.equals(atlasConversionConcern)) { Validation validation = new Validation(); validation.setField("Field.Input/Output.conversion"); validation.setMessage(atlasConversionConcern.getMessage()); validation.setStatus(ValidationStatus.INFO); validation.setValue(value); validations.add(validation); } if (atlasConversionConcern.equals(AtlasConversionConcern.RANGE) || atlasConversionConcern.equals(AtlasConversionConcern.FORMAT)) { Validation validation = new Validation(); validation.setField("Field.Input/Output.conversion"); validation.setMessage(atlasConversionConcern.getMessage()); validation.setStatus(ValidationStatus.WARN); validation.setValue(value); validations.add(validation); } if (atlasConversionConcern.equals(AtlasConversionConcern.UNSUPPORTED)) { Validation validation = new Validation(); validation.setField("Field.Input/Output.conversion"); validation.setMessage(atlasConversionConcern.getMessage()); validation.setStatus(ValidationStatus.ERROR); validation.setValue(value); validations.add(validation); } } } protected void validateFieldTypeConversion(Field inputField, Field outField, List validations) { FieldType inFieldType = inputField.getFieldType(); FieldType outFieldType = outField.getFieldType(); Optional atlasConverter = conversionService.findMatchingConverter(inFieldType, outFieldType); String rejectedValue = getFieldName(inputField) + " --> " + getFieldName(outField); if (!atlasConverter.isPresent()) { Validation validation = new Validation(); validation.setField("Field.Input/Output.conversion"); validation.setMessage( "A conversion between the input and output fields is required but no converter is available"); validation.setStatus(ValidationStatus.WARN); validation.setValue(rejectedValue); validations.add(validation); } else { AtlasConversionInfo conversionInfo; // find the method that does the conversion Method[] methods = atlasConverter.get().getClass().getMethods(); conversionInfo = Arrays.stream(methods).map(method -> method.getAnnotation(AtlasConversionInfo.class)) .filter(atlasConversionInfo -> atlasConversionInfo != null) .filter(atlasConversionInfo -> (atlasConversionInfo.sourceType().compareTo(inFieldType) == 0 && atlasConversionInfo.targetType().compareTo(outFieldType) == 0)) .findFirst().orElse(null); if (conversionInfo != null) { populateConversionConcerns(conversionInfo.concerns(), rejectedValue, validations); } } } protected String getFieldName(Field field) { if (field == null) { return "null"; } if (field.getClass().isAssignableFrom(getFieldType())) { return getModuleFieldName((T)field); } if (field.getFieldType() != null) { return field.getFieldType().name(); } return field.getClass().getName(); } protected abstract String getModuleFieldName(T field); protected AtlasConversionService getConversionService() { return conversionService; } protected void setConversionService(AtlasConversionService conversionService) { this.conversionService = conversionService; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy