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