001/*
002 * Copyright 2019 Leibniz-Institut für Analytische Wissenschaften – ISAS – e.V..
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016package de.isas.mztab2.io.validators;
017
018import de.isas.mztab2.model.MsRun;
019import de.isas.mztab2.model.Parameter;
020import de.isas.mztab2.model.SpectraRef;
021import java.util.LinkedList;
022import java.util.List;
023import java.util.Optional;
024import java.util.regex.Matcher;
025import java.util.regex.Pattern;
026import uk.ac.ebi.pride.jmztab2.model.IMZTabColumn;
027import uk.ac.ebi.pride.jmztab2.model.MZTabConstants;
028import uk.ac.ebi.pride.jmztab2.utils.errors.FormatErrorType;
029import uk.ac.ebi.pride.jmztab2.utils.errors.LogicalErrorType;
030import uk.ac.ebi.pride.jmztab2.utils.errors.MZTabError;
031import uk.ac.ebi.pride.jmztab2.utils.parser.MZTabParserContext;
032
033/**
034 *
035 * @author nilshoffmann
036 */
037public class SpectraRefValidator implements FieldValidator<List<SpectraRef>> {
038
039    @Override
040    public List<MZTabError> validateLine(int lineNumber, MZTabParserContext parserContext, IMZTabColumn column, String field, List<SpectraRef> refList) {
041        List<MZTabError> errorList = new LinkedList<>();
042        if (refList.isEmpty()) {
043            errorList.add(new MZTabError(FormatErrorType.SpectraRef,
044                    lineNumber, column.getHeader(), field));
045        } else {
046            for (SpectraRef ref : refList) {
047                MsRun run = ref.getMsRun();
048                if (!Optional.ofNullable(run.getLocation()).isPresent()) {
049                    //As the location can be null and the field is mandatory, this is not an error, it is a warning
050                    errorList.add(new MZTabError(
051                            LogicalErrorType.SpectraRef, lineNumber, column.
052                                    getHeader(), field, "ms_run[" + run.
053                                    getId() + "]-location"));
054                } else {
055                    String referenceString = ref.getReference();
056                    Parameter idFormatParam = run.getIdFormat();
057                    if (idFormatParam == null) {
058                        //fall back to scan= if nothing else is given
059                    } else {
060                        if (idFormatParam.getCvAccession() == null || idFormatParam.getCvAccession().isEmpty()) {
061                            //user param
062                        } else {
063                            //cv param
064                            String validationPattern = "";
065                            switch (idFormatParam.getCvAccession()) {
066                                case "MS:1000768": //Thermo nativeId
067                                    // "controllerType=0 controllerNumber=1 scan=1"
068                                    validationPattern = MZTabConstants.REGEX_SPECTRA_REF_THERMO_NATIVE;
069                                    break;
070                                case "MS:1000769": //Waters nativeId
071                                    // "function=0 process=0 scan=0"
072                                    validationPattern = MZTabConstants.REGEX_SPECTRA_REF_WATERS_NATIVE;
073                                    break;
074                                case "MS:1000770": //WIFF nativeId
075                                    // "sample=0 period=0 cycle=0 experiment=0"
076                                    validationPattern = MZTabConstants.REGEX_SPECTRA_REF_WIFF_NATIVE;
077                                    break;
078                                case "MS:1000774": //multiple peak list nativeID, MGF, PKL, merged DTA
079                                    // index=0
080                                    validationPattern = MZTabConstants.REGEX_SPECTRA_REF_INDEX;
081                                    break;
082                                case "MS:1000773": // Bruker FID nativeId
083                                case "MS:1000775": //file single peak list nativeId
084                                    //file=xsd:IDREF
085                                    validationPattern = MZTabConstants.REGEX_SPECTRA_REF_FILE;
086                                    break;
087                                case "MS:1000777": // spectrum identifier nativeId
088                                    //spectrum=0
089                                    validationPattern = MZTabConstants.REGEX_SPECTRA_REF_SPECTRUM;
090                                    break;
091                                case "MS:1001530": // mzML unique identifier
092                                    //xsd:string
093                                    validationPattern = MZTabConstants.REGEX_SPECTRA_REF_MZML_UNIQUE;
094                                    break;
095                                //scan instances below
096                                case "MS:1000771": //Bruker/Agilent YEP nativeId
097                                case "MS:1000772": //Bruker BAF nativeId    
098                                case "MS:1000776": //mzML scan ref
099                                    // scan=0
100                                    validationPattern = MZTabConstants.REGEX_SPECTRA_REF_SCAN;
101                                    break;
102                                default:
103                                    //As the given idFormat may be unsupported by this validator, we issue a warning!
104                                    errorList.add(new MZTabError(
105                                            LogicalErrorType.SpectraIdFormatNotSupported, lineNumber, referenceString, column.
106                                                    getHeader()));
107                            }
108                            if(!validationPattern.isEmpty()) {
109                                Optional<MZTabError> error = validatePattern(Pattern.compile(validationPattern), referenceString, lineNumber, column, field, run);
110                                if (error.isPresent()) {
111                                    errorList.add(error.get());
112                                }
113                            }
114                        }
115                    }
116                }
117            }
118        }
119        return errorList;
120    }
121
122    protected Optional<MZTabError> validatePattern(Pattern pattern, String reference, int lineNumber, IMZTabColumn column, String field, MsRun run) {
123        Matcher matcher = pattern.matcher(reference);
124
125        if (matcher.find()) {
126            return Optional.empty();
127        }
128        return Optional.of(new MZTabError(
129                LogicalErrorType.SpectraIdFormatNotValid,
130                lineNumber,
131                reference,
132                column.getHeader(),
133                pattern.toString()
134            )
135        );
136    }
137
138}