001/* 002 * Copyright 2019 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.domain; 017 018import de.isas.lipidomics.palinom.exceptions.ConstraintViolationException; 019import java.util.Collections; 020import java.util.LinkedHashMap; 021import java.util.Map; 022import java.util.Optional; 023import java.util.stream.Collectors; 024import lombok.Builder; 025import lombok.Data; 026import lombok.EqualsAndHashCode; 027import lombok.extern.slf4j.Slf4j; 028 029/** 030 * A molecular subspecies. Child of LipidSpecies. Individual FAs are known, but 031 * neither their sn positions nor double bond positions. 032 * 033 * Example: Phosphatidylinositol (8:0-8:0) or PI(8:0-8:0) 034 * 035 * @author nils.hoffmann 036 * @see LipidSpecies 037 */ 038@Slf4j 039@Data 040@EqualsAndHashCode(callSuper = true) 041public class LipidMolecularSubspecies extends LipidSpecies { 042 043 protected final Map<String, FattyAcid> fa = new LinkedHashMap<>(); 044 045 @Builder 046 public LipidMolecularSubspecies(HeadGroup headGroup, FattyAcid... fa) { 047 super(headGroup); 048 int nCarbon = 0; 049 int nHydroxyl = 0; 050 int nDoubleBonds = 0; 051 ModificationsList mods = new ModificationsList(); 052 for (FattyAcid fas : fa) { 053// if (fas.getPosition() != -1) { 054// throw new ConstraintViolationException("MolecularFattyAcid " + fas.getName() + " must have position set to -1! Was: " + fas.getPosition()); 055// } 056 if (this.fa.containsKey(fas.getName())) { 057 throw new ConstraintViolationException( 058 "FA names must be unique! FA with name " + fas.getName() + " was already added!"); 059 } else { 060 this.fa.put(fas.getName(), fas); 061 nCarbon += fas.getNCarbon(); 062 nHydroxyl += fas.getNHydroxy(); 063 nDoubleBonds += fas.getNDoubleBonds(); 064 mods.addAll(fas.getModifications()); 065 } 066 067 } 068 super.info = LipidSpeciesInfo.lipidSpeciesInfoBuilder(). 069 level(LipidLevel.MOLECULAR_SUBSPECIES). 070 name(headGroup.getName()). 071 position(-1). 072 nCarbon(nCarbon). 073 nHydroxy(nHydroxyl). 074 nDoubleBonds(nDoubleBonds). 075 lipidFaBondType(LipidFaBondType.getLipidFaBondType(headGroup, fa)). 076 modifications(mods). 077 build(); 078 } 079 080 @Override 081 public Map<String, FattyAcid> getFa() { 082 return Collections.unmodifiableMap(fa); 083 } 084 085 protected String getHeadGroupSuffix() { 086 String hgToFaSep = " "; 087 if (isEtherLipid()) { 088 hgToFaSep = " O-"; 089 } 090 return hgToFaSep; 091 } 092 093 protected StringBuilder buildSubspeciesHeadGroupString(String headGroup, boolean normalizeHeadGroup) { 094 StringBuilder lipidString = new StringBuilder(); 095 lipidString.append(Optional.ofNullable(getHeadGroup().getLipidClass()).map((lclass) -> { 096 switch (lclass) { 097// case SE: 098 case SE_27_1: 099 case SE_27_2: 100 case SE_28_2: 101 case SE_28_3: 102 case SE_29_2: 103 case SE_30_2: 104 if (!getFa().isEmpty()) { 105 return (normalizeHeadGroup ? headGroup : getNormalizedHeadGroup()) + getHeadGroupSuffix().trim() + "/"; 106 } 107 } 108 return headGroup + (getFa().isEmpty() ? "" : getHeadGroupSuffix()); 109 }).orElse(headGroup + (getFa().isEmpty() ? "" : getHeadGroupSuffix()))); 110 return lipidString; 111 } 112 113 protected String buildLipidSubspeciesName(LipidLevel level, String faSeparator, String headGroup, boolean isNormalized) { 114 StringBuilder sb = new StringBuilder(); 115 String faStrings = getFa().values().stream().map((fa) -> { 116 return fa.buildSubstructureName(level); 117 }).collect(Collectors.joining(faSeparator)); 118 return sb.append(buildSubspeciesHeadGroupString(headGroup, isNormalized) 119 ).append(faStrings).toString(); 120 } 121 122 @Override 123 public String getLipidString(LipidLevel level) { 124 return this.getLipidString(level, false); 125 } 126 127 @Override 128 public String getLipidString(LipidLevel level, boolean normalizeHeadGroup) { 129 String headGroup = normalizeHeadGroup ? getNormalizedHeadGroup() : getHeadGroup().getName(); 130 switch (level) { 131 case MOLECULAR_SUBSPECIES: 132 return buildLipidSubspeciesName(level, "-", headGroup, normalizeHeadGroup); 133 case CATEGORY: 134 case CLASS: 135 case SPECIES: 136 return super.getLipidString(level, normalizeHeadGroup); 137 default: 138 LipidLevel thisLevel = getInfo().getLevel(); 139 throw new ConstraintViolationException(getClass().getSimpleName() + " can not create a string for lipid with level " + thisLevel + " for level " + level + ": target level is more specific than this lipid's level!"); 140 } 141 } 142 143 @Override 144 public String getNormalizedLipidString() { 145 return getLipidString(getInfo().getLevel(), true); 146 } 147 148 @Override 149 public boolean validate() { 150 return true; 151 } 152 153 @Override 154 public String toString() { 155 return getLipidString(); 156 } 157 158}