/* * Copyright (C) 2006-2016 DLR, Germany * * All rights reserved * * http://www.rcenvironment.de/ */ package de.rcenvironment.components.outputwriter.execution.validator; import java.io.IOException; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.commons.logging.LogFactory; import org.codehaus.jackson.annotate.JsonMethod; import org.codehaus.jackson.annotate.JsonAutoDetect.Visibility; import org.codehaus.jackson.map.ObjectMapper; import de.rcenvironment.components.outputwriter.common.OutputLocation; import de.rcenvironment.components.outputwriter.common.OutputLocationList; import de.rcenvironment.components.outputwriter.common.OutputWriterComponentConstants; import de.rcenvironment.components.outputwriter.execution.Messages; import de.rcenvironment.core.component.model.api.ComponentDescription; import de.rcenvironment.core.component.model.endpoint.api.EndpointDescription; import de.rcenvironment.core.component.validation.api.ComponentValidationMessage; import de.rcenvironment.core.component.validation.spi.AbstractComponentValidator; import de.rcenvironment.core.datamodel.api.DataType; import de.rcenvironment.core.utils.common.JsonUtils; /** * Validator for output writer component. * * @author Sascha Zur * @author Jascha Riedel */ public class OutputWriterComponentValidator extends AbstractComponentValidator { private static final int MINUS_ONE = -1; @Override public String getIdentifier() { return OutputWriterComponentConstants.COMPONENT_ID; } @Override protected List<ComponentValidationMessage> validateComponentSpecific(ComponentDescription componentDescription) { final List<ComponentValidationMessage> messages = new LinkedList<ComponentValidationMessage>(); String chooseAtStart = getProperty(componentDescription, OutputWriterComponentConstants.CONFIG_KEY_ONWFSTART); if (!Boolean.parseBoolean(chooseAtStart) && getProperty(componentDescription, OutputWriterComponentConstants.CONFIG_KEY_ROOT).isEmpty()) { final ComponentValidationMessage noDirectory = new ComponentValidationMessage( ComponentValidationMessage.Type.ERROR, OutputWriterComponentConstants.CONFIG_KEY_ROOT, Messages.noRootChosen, Messages.bind(Messages.noRootChosen, OutputWriterComponentConstants.CONFIG_KEY_ROOT)); messages.add(noDirectory); } // Validate OutputLocations String outputLocString = getProperty(componentDescription, OutputWriterComponentConstants.CONFIG_KEY_OUTPUTLOCATIONS); ObjectMapper jsonMapper = JsonUtils.getDefaultObjectMapper(); jsonMapper.setVisibility(JsonMethod.ALL, Visibility.ANY); if (outputLocString == null) { outputLocString = "{}"; } try { OutputLocationList outputList = jsonMapper.readValue(outputLocString, OutputLocationList.class); List<String> inputNamesHavingOutput = new ArrayList<String>(); for (OutputLocation out : outputList.getOutputLocations()) { inputNamesHavingOutput.addAll(out.getInputs()); // Check if OutputLocation has at least one input if (out.getInputs().isEmpty()) { final ComponentValidationMessage outputWithoutInput = new ComponentValidationMessage( ComponentValidationMessage.Type.WARNING, out.getFilename(), Messages.noInputForOutput, Messages.bind(Messages.noInputForOutput, out.getFilename())); messages.add(outputWithoutInput); } // Check if all inputs still exist and if they are connected boolean connectedInputs = false; boolean unconnectedInputs = false; for (String inputName : out.getInputs()) { boolean stillExists = false; for (EndpointDescription ed : getInputs(componentDescription)) { if (ed.getName().equals(inputName)) { stillExists = true; if (ed.isConnected()) { connectedInputs = true; } else { unconnectedInputs = true; } } } if (!stillExists) { final ComponentValidationMessage missingInput = new ComponentValidationMessage( ComponentValidationMessage.Type.ERROR, out.getFilename(), Messages.missingInput, Messages.bind(Messages.missingInput, out.getFilename(), inputName)); messages.add(missingInput); } } // If all inputs of a target are connected or all are // unconnected, there is no problem. // But if some are connected and some are not, the workflow will // probably fail. if (connectedInputs && unconnectedInputs) { final ComponentValidationMessage connectedAndUnconnectedInputs = new ComponentValidationMessage( ComponentValidationMessage.Type.WARNING, out.getFilename(), Messages.connectedAndUnconnectedInputs, Messages.bind(Messages.connectedAndUnconnectedInputs, out.getFilename())); messages.add(connectedAndUnconnectedInputs); } // Check if all the placeholders can be resolved String formatString = out.getFormatString(); Matcher matcher = Pattern.compile("\\" + OutputWriterComponentConstants.PH_PREFIX + "([^\\" + OutputWriterComponentConstants.PH_SUFFIX + "]+)").matcher(formatString); List<String> placeholders = new ArrayList<>(); int pos = MINUS_ONE; while (matcher.find(pos + 1)) { pos = matcher.start(); placeholders.add(matcher.group(1)); } for (String placeholder : placeholders) { if (placeholder.equals(OutputWriterComponentConstants.TIMESTAMP) || placeholder.equals(OutputWriterComponentConstants.LINEBREAK) || placeholder.equals(OutputWriterComponentConstants.EXECUTION_COUNT)) { continue; } else { boolean foundMatch = false; for (String input : out.getInputs()) { if (placeholder.equals(input)) { foundMatch = true; break; } } if (foundMatch) { continue; } } // No input matched this placeholder final ComponentValidationMessage unmatchedPlaceholder = new ComponentValidationMessage( ComponentValidationMessage.Type.WARNING, placeholder, Messages.unmatchedPlaceholder, Messages.bind(Messages.unmatchedPlaceholder, out.getFilename(), placeholder)); messages.add(unmatchedPlaceholder); } // Check if all the header placeholders can be resolved String header = out.getHeader(); matcher = Pattern.compile("\\" + OutputWriterComponentConstants.PH_PREFIX + "([^\\" + OutputWriterComponentConstants.PH_SUFFIX + "]+)").matcher(header); List<String> headerPlaceholders = new ArrayList<>(); pos = MINUS_ONE; while (matcher.find(pos + 1)) { pos = matcher.start(); headerPlaceholders.add(matcher.group(1)); } for (String placeholder : headerPlaceholders) { if (placeholder.equals(OutputWriterComponentConstants.TIMESTAMP) || placeholder.equals(OutputWriterComponentConstants.LINEBREAK) || placeholder.equals(OutputWriterComponentConstants.EXECUTION_COUNT)) { continue; } // No input matched this placeholder final ComponentValidationMessage unmatchedHeaderPlaceholder = new ComponentValidationMessage( ComponentValidationMessage.Type.WARNING, placeholder, Messages.unmatchedHeaderPlaceholder, Messages.bind(Messages.unmatchedHeaderPlaceholder, out.getFilename(), placeholder)); messages.add(unmatchedHeaderPlaceholder); } } // Check if every simple data input is connected to an // OutputLocation for (EndpointDescription ed : getInputs(componentDescription)) { if (!ed.getDataType().equals(DataType.FileReference) && !ed.getDataType().equals(DataType.DirectoryReference)) { if (!inputNamesHavingOutput.contains(ed.getName())) { final ComponentValidationMessage inputWithoutOutput = new ComponentValidationMessage( ComponentValidationMessage.Type.WARNING, ed.getName(), Messages.noOutputForInput, Messages.bind(Messages.noOutputForInput, ed.getName())); messages.add(inputWithoutOutput); } } } } catch (IOException e) { LogFactory.getLog(getClass()).debug("Could not validate OutputLocation configuration " + e.getMessage()); } return messages; } @Override protected List<ComponentValidationMessage> validateOnWorkflowStartComponentSpecific( ComponentDescription componentDescription) { // TODO Auto-generated method stub return null; } }