001/* 002 * Copyright 2020 nils.hoffmann. 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.lipidomics.palinom.goslinfragments; 017 018import de.isas.lipidomics.domain.Adduct; 019import de.isas.lipidomics.domain.Fragment; 020import de.isas.lipidomics.domain.LipidAdduct; 021import de.isas.lipidomics.domain.LipidCategory; 022import de.isas.lipidomics.domain.LipidSpecies; 023import de.isas.lipidomics.palinom.GoslinFragmentsBaseVisitor; 024import de.isas.lipidomics.palinom.GoslinFragmentsParser; 025import de.isas.lipidomics.palinom.exceptions.ParseTreeVisitorException; 026import java.util.Arrays; 027import java.util.BitSet; 028import java.util.Optional; 029import lombok.extern.slf4j.Slf4j; 030 031/** 032 * Base visitor implementation for the GoslinFragments grammar. 033 * 034 * Overriding implementation of {@link GoslinFragmentsBaseVisitor}. Creates 035 * {@link LipidAdduct} instances from the provided context. 036 * 037 * @author nils.hoffmann 038 */ 039@Slf4j 040public class GoslinFragmentsVisitorImpl extends GoslinFragmentsBaseVisitor<LipidAdduct> { 041 042 /** 043 * Produces a LipidAdduct given the LipidContext. 044 * 045 * @throws ParseTreeVisitorException for structural or state-related issues 046 * while trying to process a parsing context. 047 * @throws RuntimeException 048 * @param ctx 049 * @return a LipidAdduct. 050 */ 051 @Override 052 public LipidAdduct visitLipid(GoslinFragmentsParser.LipidContext ctx) { 053 GoslinFragmentsParser.Lipid_eofContext lipid = ctx.lipid_eof(); 054 Optional<GoslinFragmentsParser.Fragment_nameContext> fragmentContext = Optional.ofNullable(lipid.fragment_name()); 055 Optional<GoslinFragmentsParser.Lipid_pureContext> lipidContext = Optional.ofNullable(lipid.just_lipid().lipid_pure()); 056 Optional<GoslinFragmentsParser.Adduct_infoContext> adductTermContext = Optional.ofNullable(lipid.just_lipid().adduct_info()); 057 LipidAdduct la = new LipidAdduct(lipidContext.map((cc) -> { 058 return new GoslinFragmentsVisitorImpl.LipidVisitor().visitLipid_pure(cc); 059 }).orElse(LipidSpecies.NONE), adductTermContext.map((t) -> { 060 return new GoslinFragmentsVisitorImpl.AdductVisitor().visitAdduct_info(t); 061 }).orElse(Adduct.NONE), fragmentContext.map((t) -> { 062 return new Fragment(t.frag_char().getText()); 063 }).orElse(Fragment.NONE)); 064 return la; 065 } 066 067 private static class LipidVisitor extends GoslinFragmentsBaseVisitor<LipidSpecies> { 068 069 @Override 070 public LipidSpecies visitLipid_pure(GoslinFragmentsParser.Lipid_pureContext ctx) { 071 LipidSpecies lipid = null; 072 BitSet bs = new BitSet(5); 073 bs.set(LipidCategory.ST.ordinal(), ctx.sterol() != null); 074 bs.set(LipidCategory.GL.ordinal(), ctx.gl() != null); 075 bs.set(LipidCategory.FA.ordinal(), ctx.mediatorc() != null); 076 bs.set(LipidCategory.GP.ordinal(), ctx.pl() != null); 077 bs.set(LipidCategory.SP.ordinal(), ctx.sl() != null); 078 final FattyAcylHelper faHelper = new FattyAcylHelper(); 079 final MolecularSubspeciesFasHandler msfh = new MolecularSubspeciesFasHandler(faHelper); 080 final IsomericSubspeciesFasHandler isfh = new IsomericSubspeciesFasHandler(faHelper); 081 final StructuralSubspeciesFasHandler ssfh = new StructuralSubspeciesFasHandler(isfh, faHelper); 082 final IsomericSubspeciesLcbHandler islh = new IsomericSubspeciesLcbHandler(isfh, faHelper); 083 final StructuralSubspeciesLcbHandler sslh = new StructuralSubspeciesLcbHandler(ssfh, islh); 084 final FattyAcylHandler faHandler = new FattyAcylHandler(); 085 LipidCategory contextCategory = LipidCategory.UNDEFINED; 086 switch (bs.cardinality()) { 087 case 0: 088 throw new ParseTreeVisitorException("Parsing context did not contain content for any lipid category. Must contain exactly one of " + Arrays.toString(LipidCategory.values())); 089 case 1: 090 contextCategory = LipidCategory.values()[bs.nextSetBit(0)]; 091 break; 092 default: 093 throw new ParseTreeVisitorException("Parsing context contained content for more than one lipid category. Must contain exactly one of " + Arrays.toString(LipidCategory.values())); 094 } 095 switch (contextCategory) { 096 case ST: 097 lipid = new SterolLipidHandler( 098 ssfh 099 ).handle(ctx); 100 break; 101 case GL: 102 lipid = new GlyceroLipidHandler( 103 msfh, 104 ssfh, 105 faHandler 106 ).handle(ctx); 107 break; 108 case FA: 109 lipid = new FattyAcylHandler().handle(ctx); 110 break; 111 case GP: 112 lipid = new GlycerophosphoLipidHandler( 113 msfh, 114 ssfh, 115 faHandler 116 ).handle(ctx); 117 break; 118 case SP: 119 lipid = new SphingoLipidHandler( 120 sslh, 121 faHandler 122 ).handle(ctx); 123 break; 124 default: 125 throw new ParseTreeVisitorException("Unhandled contextCategory: " + contextCategory); 126 } 127 return lipid; 128 } 129 130 } 131 132 private static class AdductVisitor extends GoslinFragmentsBaseVisitor<Adduct> { 133 134 @Override 135 public Adduct visitAdduct_info(GoslinFragmentsParser.Adduct_infoContext ctx) { 136 String chargeSign = ctx.charge_sign().getText(); 137 Integer chargeSignValue = 0; 138 switch (chargeSign) { 139 case "+": 140 chargeSignValue = 1; 141 break; 142 case "-": 143 chargeSignValue = -1; 144 break; 145 default: 146 chargeSignValue = 0; 147 } 148 String adductText = ctx.adduct().getText(); 149 Adduct adduct = new Adduct("", adductText, Integer.parseInt(ctx.charge().getText()), chargeSignValue); 150 return adduct; 151 } 152 } 153}