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.Optional;
020import java.util.stream.Collectors;
021import lombok.Builder;
022import lombok.Data;
023import lombok.EqualsAndHashCode;
024
025/**
026 * An isomeric subspecies. Child of LipidStructuralSubspecies. Individual FAs,
027 * their sn positions, and the double bond positions are known.
028 *
029 * Example: PE(P-18:0/22:6(4Z,7Z,10Z,13Z,16Z,19Z))
030 *
031 * @author nils.hoffmann
032 * @see LipidStructuralSubspecies
033 */
034@Data
035@EqualsAndHashCode(callSuper = true)
036public class LipidIsomericSubspecies extends LipidStructuralSubspecies {
037
038    /**
039     * Creates a new LipidIsomericSubspecies.
040     *
041     * @param headGroup the head group for this lipid.
042     * @param fa the FattyAcids attached to this lipid.
043     */
044    @Builder(builderMethodName = "lipidIsomericSubspeciesBuilder")
045    public LipidIsomericSubspecies(HeadGroup headGroup, FattyAcid... fa) {
046        super(headGroup);
047        int nCarbon = 0;
048        int nHydroxyl = 0;
049        int nDoubleBonds = 0;
050        ModificationsList mods = new ModificationsList();
051        for (FattyAcid fas : fa) {
052            if (super.fa.containsKey(fas.getName())) {
053                throw new ConstraintViolationException(
054                        "FA names must be unique! FA with name " + fas.getName() + " was already added!");
055            } else {
056                super.fa.put(fas.getName(), fas);
057                nCarbon += fas.getNCarbon();
058                nHydroxyl += fas.getNHydroxy();
059                nDoubleBonds += fas.getNDoubleBonds();
060                mods.addAll(fas.getModifications());
061            }
062        }
063        super.info = Optional.of(
064                LipidSpeciesInfo.lipidSpeciesInfoBuilder().
065                        level(LipidLevel.ISOMERIC_SUBSPECIES).
066                        name(headGroup.getName()).
067                        position(-1).
068                        nCarbon(nCarbon).
069                        nHydroxy(nHydroxyl).
070                        nDoubleBonds(nDoubleBonds).
071                        lipidFaBondType(LipidFaBondType.getLipidFaBondType(headGroup, fa)).
072                        modifications(mods).
073                        build()
074        );
075    }
076
077    private String buildLipidIsomericSubstructureName(LipidLevel level, String headGroup, boolean isNormalized) {
078        StringBuilder sb = new StringBuilder();
079        String faStrings = getFa().values().stream().map((fa) -> {
080            return fa.buildSubstructureName(level);
081        }).collect(Collectors.joining("/"));
082        return sb.append(
083                buildSubspeciesHeadGroupString(headGroup, isNormalized)
084        ).append(faStrings).toString();
085    }
086
087    @Override
088    public String getLipidString(LipidLevel level, boolean normalizeHeadGroup) {
089        String headGroup = normalizeHeadGroup ? getNormalizedHeadGroup() : getHeadGroup().getName();
090        switch (level) {
091            case ISOMERIC_SUBSPECIES:
092                return buildLipidIsomericSubstructureName(level, headGroup, normalizeHeadGroup);
093            case STRUCTURAL_SUBSPECIES:
094            case MOLECULAR_SUBSPECIES:
095            case CATEGORY:
096            case CLASS:
097            case SPECIES:
098                return super.getLipidString(level, normalizeHeadGroup);
099            default:
100                LipidLevel thisLevel = getInfo().orElse(LipidSpeciesInfo.NONE).getLevel();
101                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!");
102        }
103    }
104
105    @Override
106    public String getLipidString(LipidLevel level) {
107        return this.getLipidString(level, false);
108    }
109
110    @Override
111    public String getNormalizedLipidString() {
112        return getLipidString(getInfo().orElse(LipidSpeciesInfo.NONE).getLevel(), true);
113    }
114
115    @Override
116    public String toString() {
117        return getLipidString();
118    }
119}