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 uk.ac.ebi.pride.jmztab2.utils.parser; 017 018import de.isas.mztab2.model.Assay; 019import de.isas.mztab2.model.Metadata; 020import de.isas.mztab2.model.Parameter; 021import java.util.*; 022import org.slf4j.Logger; 023import org.slf4j.LoggerFactory; 024import uk.ac.ebi.pride.jmztab2.model.IMZTabColumn; 025import uk.ac.ebi.pride.jmztab2.model.ISmallMoleculeFeatureColumn; 026import uk.ac.ebi.pride.jmztab2.model.MZTabColumnFactory; 027import uk.ac.ebi.pride.jmztab2.model.MZTabConstants; 028import uk.ac.ebi.pride.jmztab2.model.Section; 029import uk.ac.ebi.pride.jmztab2.model.SmallMoleculeFeatureColumn; 030import uk.ac.ebi.pride.jmztab2.utils.errors.FormatErrorType; 031import uk.ac.ebi.pride.jmztab2.utils.errors.LogicalErrorType; 032import uk.ac.ebi.pride.jmztab2.utils.errors.MZTabError; 033import uk.ac.ebi.pride.jmztab2.utils.errors.MZTabErrorList; 034import uk.ac.ebi.pride.jmztab2.utils.errors.MZTabException; 035 036/** 037 * Parse and validate Small Molecule Feature header line into a {@link uk.ac.ebi.pride.jmztab2.model.MZTabColumnFactory}. 038 * 039 * @author nilshoffmann 040 * @since 11/09/17 041 * 042 */ 043public class SFHLineParser extends MZTabHeaderLineParser { 044 045 private static final Logger LOGGER = LoggerFactory.getLogger(SFHLineParser.class); 046 private Map<Integer, String> physPositionToOrder; 047 048 049 /** 050 * <p>Constructor for SFHLineParser.</p> 051 * 052 * @param context a {@link uk.ac.ebi.pride.jmztab2.utils.parser.MZTabParserContext} object. 053 * @param metadata a {@link de.isas.mztab2.model.Metadata} object. 054 */ 055 public SFHLineParser(MZTabParserContext context, Metadata metadata) { 056 super(context, MZTabColumnFactory.getInstance(Section.Small_Molecule_Feature_Header), metadata); 057 } 058 059 /** {@inheritDoc} */ 060 @Override 061 protected int parseColumns() throws MZTabException { 062 String header; 063 Integer physicalPosition; 064 065 ISmallMoleculeFeatureColumn column; 066 SortedMap<String, IMZTabColumn> columnMapping = factory.getColumnMapping(); 067 SortedMap<String, IMZTabColumn> optionalMapping = factory.getOptionalColumnMapping(); 068 SortedMap<String, IMZTabColumn> stableMapping = factory.getStableColumnMapping(); 069 070 physPositionToOrder = generateHeaderPhysPositionToOrderMap(items); 071 072 //Iterates through the tokens in the protein header 073 //It will identify the type of column and the position accordingly 074 for (physicalPosition = 1; physicalPosition < items.length; physicalPosition++) { 075 076 column = null; 077 header = items[physicalPosition]; 078 079 if (header.contains(MZTabConstants.ABUNDANCE_PREFIX)) { 080 checkAbundanceColumns(physicalPosition, physPositionToOrder.get(physicalPosition)); 081 } else if (header.startsWith(MZTabConstants.OPT_PREFIX)) { 082 checkOptColumnName(header); 083 } else { 084 try { 085 column = SmallMoleculeFeatureColumn.Stable.columnFor(header); 086 } catch(IllegalArgumentException ex) { 087 throw new MZTabException(new MZTabError(LogicalErrorType.ColumnNotValid,lineNumber,header,section.getName())); 088 } 089 090 } 091 092 if (column != null) { 093 if (!column.getOrder().equals(physPositionToOrder.get(physicalPosition))) { 094 column.setOrder(physPositionToOrder.get(physicalPosition)); 095 LOGGER.debug(column.toString()); 096 } 097 if(column.isOptional()){ 098 optionalMapping.put(column.getLogicPosition(), column); 099 } else { 100 stableMapping.put(column.getLogicPosition(), column); 101 } 102 columnMapping.put(column.getLogicPosition(), column); 103 } 104 } 105 return physicalPosition; 106 } 107 108 private Map<Integer, String> generateHeaderPhysPositionToOrderMap(String[] items) { 109 Integer physicalPosition; 110 Map<Integer, String> physicalPositionToOrder = new LinkedHashMap<>(); 111 int order = 0; 112 113 for (physicalPosition = 1; physicalPosition < items.length; physicalPosition++) { 114 if(physicalPositionToOrder.containsKey(physicalPosition)) { 115 throw new IllegalArgumentException("Physical position "+physicalPosition+" for item "+items[physicalPosition-1]+" is already assigned!"); 116 } 117 physicalPositionToOrder.put(physicalPosition, fromIndexToOrder(++order)); 118 } 119 return physicalPositionToOrder; 120 } 121 122 /** 123 * {@inheritDoc} 124 * 125 * The following optional columns are mandatory: 126 * 1. abundance_assay[1-n] 127 * 128 * NOTICE: this method will be called at end of parse() function. 129 * @see MZTabHeaderLineParser#parse(int, String, MZTabErrorList) 130 * @see MZTabHeaderLineParser#parse(int, String, MZTabErrorList) 131 */ 132 @Override 133 protected void refine() throws MZTabException { 134 135 //mandatory columns 136 List<String> mandatoryColumnHeaders = new ArrayList<>(); 137 for(ISmallMoleculeFeatureColumn column: SmallMoleculeFeatureColumn.Stable.columns()) { 138 mandatoryColumnHeaders.add(column.getName()); 139 } 140 141 Parameter smallMoleculeFeatureQuantificationUnit = Optional.ofNullable(metadata.getSmallMoleculeFeatureQuantificationUnit()).orElseThrow(() -> 142 new MZTabException(new MZTabError(LogicalErrorType.NoSmallMoleculeFeatureQuantificationUnit, lineNumber))); 143 144 for (String columnHeader : mandatoryColumnHeaders) { 145 if (factory.findColumnByHeader(columnHeader) == null) { 146 throw new MZTabException(new MZTabError(FormatErrorType.StableColumn, lineNumber, columnHeader)); 147 } 148 } 149 150 for (Assay assay : metadata.getAssay()) { 151 String assayLabel = "_"+Metadata.Properties.assay+"[" + assay.getId() + "]"; 152 refineOptionalColumn(Section.Small_Molecule_Feature_Header, "abundance" + assayLabel); 153 } 154 } 155}