001/* 002 * Copyright 2018 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.validation; 017 018import de.isas.lipidomics.mztab2.validation.Validator; 019import de.isas.mztab2.cvmapping.JxPathElement; 020import de.isas.mztab2.cvmapping.SetOperations; 021import de.isas.mztab2.io.serialization.ParameterConverter; 022import de.isas.mztab2.model.CV; 023import de.isas.mztab2.model.MzTab; 024import de.isas.mztab2.model.Parameter; 025import de.isas.mztab2.model.ValidationMessage; 026import java.util.ArrayList; 027import java.util.HashSet; 028import java.util.List; 029import java.util.Map; 030import java.util.Set; 031import java.util.stream.Collectors; 032import lombok.extern.slf4j.Slf4j; 033import org.apache.commons.jxpath.JXPathContext; 034import org.apache.commons.jxpath.Pointer; 035import org.apache.commons.lang3.tuple.Pair; 036import uk.ac.ebi.pride.jmztab2.utils.errors.CrossCheckErrorType; 037import uk.ac.ebi.pride.jmztab2.utils.errors.MZTabError; 038 039/** 040 * Validates that controlled vocabularies used by parameters are defined in the 041 * metadata CV section. 042 * 043 * @author nilshoffmann 044 */ 045@Slf4j 046@lombok.Builder() 047public class CvDefinitionValidationHandler implements Validator<MzTab> { 048 049 @Override 050 public List<ValidationMessage> validate(MzTab mzTab) { 051 JXPathContext context = JXPathContext.newContext(mzTab); 052 return checkCvDefinitions(mzTab, context); 053 } 054 055 private List<ValidationMessage> checkCvDefinitions(MzTab mzTabFile, 056 JXPathContext context) { 057 Map<String, CV> cvTerms = mzTabFile.getMetadata(). 058 getCv(). 059 stream(). 060 collect(Collectors.toMap((key) -> 061 { 062 return key.getLabel(); 063 }, (value) -> 064 { 065 return value; 066 })); 067 List<ValidationMessage> messages = new ArrayList<>(); 068 List<Pair<Pointer, Parameter>> parameters = JxPathElement. 069 toList(context, "//*[cvLabel!='']", 070 Parameter.class); 071 log.debug("Selected {} cv parameters!", parameters.size()); 072 Set<String> definedCvLabels = new HashSet<>(cvTerms.keySet()); 073 Set<String> usedCvLabels = new HashSet<>(); 074 parameters.stream(). 075 forEach((t) -> 076 { 077 Parameter param = t.getValue(); 078 log.debug("Checking parameter {}", new ParameterConverter(). 079 convert(param)); 080 if (param.getCvLabel() != null && !param.getCvLabel(). 081 isEmpty()) { 082 usedCvLabels.add(param.getCvLabel()); 083 if (!cvTerms.containsKey(param.getCvLabel())) { 084 log.debug( 085 "Parameter {} uses undefined controlled vocabulary: {}", 086 new ParameterConverter(). 087 convert(param), param.getCvLabel()); 088 MZTabError error = new MZTabError( 089 CrossCheckErrorType.CvUndefinedInMetadata, -1, 090 param.getCvLabel(), 091 new ParameterConverter().convert(param)); 092 messages.add(error.toValidationMessage()); 093 } 094 } 095 }); 096 Set<String> unusedCvLabels = SetOperations.complement(definedCvLabels, 097 usedCvLabels); 098 unusedCvLabels.stream(). 099 forEach((cvLabel) -> 100 { 101 log.debug( 102 "Cv with label {} is not being used by any parameters!", 103 cvLabel); 104 MZTabError error = new MZTabError( 105 CrossCheckErrorType.CvUnused, -1, 106 cvLabel); 107 messages.add(error.toValidationMessage()); 108 }); 109 return messages; 110 } 111}