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.hmdb; 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.HMDBBaseVisitor; 024import de.isas.lipidomics.palinom.HMDBParser; 025import de.isas.lipidomics.palinom.exceptions.ParseTreeVisitorException; 026import java.util.Arrays; 027import java.util.BitSet; 028import java.util.Optional; 029 030/** 031 * Base visitor implementation for the GoslinFragments grammar. 032 * 033 * Overriding implementation of {@link HMDBBaseVisitor}. Creates 034 * {@link LipidAdduct} instances from the provided context. 035 * 036 * @see HmdbVisitorParser 037 * @author nils.hoffmann 038 */ 039public class HmdbVisitorImpl extends HMDBBaseVisitor<LipidAdduct> { 040 041 /** 042 * Produces a LipidAdduct given the LipidContext. 043 * @throws ParseTreeVisitorException for structural or state-related issues 044 * while trying to process a parsing context. 045 * @throws RuntimeException 046 * @param ctx 047 * @return a LipidAdduct. 048 */ 049 @Override 050 public LipidAdduct visitLipid(HMDBParser.LipidContext ctx) { 051 Optional<HMDBParser.Lipid_pureContext> categoryContext = Optional.ofNullable(ctx.lipid_pure()); 052 053 LipidAdduct la = new LipidAdduct(categoryContext.map((cc) -> { 054 return new LipidVisitor().visitLipid_pure(cc); 055 }).orElse(LipidSpecies.NONE), Adduct.NONE, new Fragment("")); 056 return la; 057 } 058 059 private static class LipidVisitor extends HMDBBaseVisitor<LipidSpecies> { 060 061 @Override 062 public LipidSpecies visitLipid_pure(HMDBParser.Lipid_pureContext ctx) { 063 LipidSpecies lipid = null; 064 BitSet bs = new BitSet(5); 065 bs.set(LipidCategory.ST.ordinal(), ctx.lipid_class().st() != null); 066 bs.set(LipidCategory.GL.ordinal(), ctx.lipid_class().gl() != null); 067 bs.set(LipidCategory.FA.ordinal(), ctx.lipid_class().fatty_acid() != null); 068 bs.set(LipidCategory.GP.ordinal(), ctx.lipid_class().pl() != null); 069 bs.set(LipidCategory.SP.ordinal(), ctx.lipid_class().sl() != null); 070 final FattyAcylHelper faHelper = new FattyAcylHelper(); 071 final MolecularSubspeciesFasHandler msfh = new MolecularSubspeciesFasHandler(faHelper); 072 final IsomericSubspeciesFasHandler isfh = new IsomericSubspeciesFasHandler(faHelper); 073 final StructuralSubspeciesFasHandler ssfh = new StructuralSubspeciesFasHandler(isfh, faHelper); 074 final IsomericSubspeciesLcbHandler islh = new IsomericSubspeciesLcbHandler(isfh, faHelper); 075 final StructuralSubspeciesLcbHandler sslh = new StructuralSubspeciesLcbHandler(ssfh, islh, faHelper); 076 final FattyAcylHandler faHandler = new FattyAcylHandler(); 077 String lipidSuffix = ""; 078 if (ctx.lipid_suffix() != null) { 079 lipidSuffix = ctx.lipid_suffix().getText(); 080 throw new ParseTreeVisitorException("The lipid suffix '" + lipidSuffix + "' is currently unsupported. Please contact the developers at https://lifs.isas.de/support for assistance."); 081 } 082 LipidCategory contextCategory = LipidCategory.UNDEFINED; 083 switch (bs.cardinality()) { 084 case 0: 085 throw new ParseTreeVisitorException("Parsing context did not contain content for any lipid category. Must contain exactly one of " + Arrays.toString(LipidCategory.values())); 086 case 1: 087 contextCategory = LipidCategory.values()[bs.nextSetBit(0)]; 088 break; 089 default: 090 throw new ParseTreeVisitorException("Parsing context contained content for more than one lipid category. Must contain exactly one of " + Arrays.toString(LipidCategory.values())); 091 } 092 switch (contextCategory) { 093 case ST: 094 lipid = new SterolLipidHandler( 095 msfh, 096 ssfh, 097 isfh, 098 faHandler 099 ).handle(ctx); 100 break; 101 case GL: 102 lipid = new GlyceroLipidHandler( 103 msfh, 104 ssfh, 105 isfh, 106 faHandler 107 ).handle(ctx); 108 break; 109 case FA: 110 lipid = new FattyAcylHandler().handle(ctx); 111 break; 112 case GP: 113 lipid = new GlycerophosphoLipidHandler( 114 msfh, 115 ssfh, 116 isfh, 117 faHandler 118 ).handle(ctx); 119 break; 120 case SP: 121 lipid = new SphingoLipidHandler( 122 sslh, 123 islh, 124 faHandler 125 ).handle(ctx); 126 break; 127 default: 128 throw new ParseTreeVisitorException("Unhandled contextCategory: " + contextCategory); 129 } 130 return lipid; 131 } 132 } 133}