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 java.util.Map;
019import lombok.Builder;
020import lombok.Data;
021import lombok.EqualsAndHashCode;
022
023/**
024 * This class summarizes the FA parts of a lipid, independent of its head group.
025 * Thus, it accounts the total number of carbon atoms, double bonds, the number
026 * of hydroxylations, the overall FA-headgroup bond type, e.g. PLASMANYL /
027 * PLASMENYL, if any of a lipid's FA chains has such a bond type, or ESTER or
028 * UNDEFINED for other cases.
029 *
030 * @author nils.hoffmann
031 */
032@Data
033@EqualsAndHashCode(callSuper = true)
034public class LipidSpeciesInfo extends FattyAcid {
035
036    private static final class None extends LipidSpeciesInfo {
037
038        private None() {
039            super(LipidLevel.UNDEFINED, "NONE", -1, 0, 0, 0, LipidFaBondType.UNDEFINED, false, ModificationsList.NONE);
040        }
041    }
042
043    /**
044     * Use this class to indicate that no lipid species info is available.
045     */
046    public static final LipidSpeciesInfo NONE = new LipidSpeciesInfo.None();
047
048    private final LipidLevel level;
049
050    /**
051     * Create a new LipidSpeciesInfo on the provided level.
052     *
053     * @param level the level of the species info.
054     * @param name the name, e.g. FA1 for the first FA.
055     * @param position the sn position. -1 if undefined or unknown.
056     * @param nCarbon the number of carbons in this FA.
057     * @param nHydroxy the number of hydroxyls on this FA.
058     * @param nDoubleBonds the number of double bonds in this FA.
059     * @param lipidFaBondType the bond type, e.g. ESTER.
060     * @param lcb true if this is a long-chain base, e.g. in a Ceramide.
061     * @param modifications optional modifications for this FA.
062     * @see LipidFaBondType
063     */
064    @Builder(builderMethodName = "lipidSpeciesInfoBuilder")
065    public LipidSpeciesInfo(LipidLevel level, String name, int position, int nCarbon, int nHydroxy, int nDoubleBonds, LipidFaBondType lipidFaBondType, boolean lcb, ModificationsList modifications) {
066        super(name, position, nCarbon, nHydroxy, nDoubleBonds, lipidFaBondType, lcb, modifications);
067        this.level = level;
068    }
069
070    /**
071     * Create a new LipidSpeciesInfo on the provided level.
072     *
073     * @param level the level of the species info.
074     * @param name the name, e.g. FA1 for the first FA.
075     * @param position the sn position. -1 if undefined or unknown.
076     * @param nCarbon the number of carbons in this FA.
077     * @param nHydroxy the number of hydroxyls on this FA.
078     * @param lipidFaBondType the bond type, e.g. ESTER.
079     * @param lcb true if this is a long-chain base, e.g. in a Ceramide.
080     * @param modifications optional modifications for this FA.
081     * @param nDoubleBonds the number of double bonds in this FA.
082     * @param doubleBondPositions double bond positions in this FA.
083     * @see LipidFaBondType
084     */
085    @Builder(builderMethodName = "lipidSubspeciesInfoBuilder", builderClassName = "LipidSubspeciesInfoBuilder")
086    public LipidSpeciesInfo(LipidLevel level, String name, int position, int nCarbon, int nHydroxy, LipidFaBondType lipidFaBondType, boolean lcb, ModificationsList modifications, int nDoubleBonds, Map<Integer, String> doubleBondPositions) {
087        super(name, position, nCarbon, nHydroxy, lipidFaBondType, lcb, modifications, nDoubleBonds, doubleBondPositions);
088        this.level = level;
089    }
090
091    /**
092     * Create a new LipidSpeciesInfo on the provided level.The name is inferred
093     * from the level.
094     *
095     * @param level the level of the species info.
096     * @param nCarbon the number of carbons in this FA.
097     * @param nHydroxy the number of hydroxyls on this FA.
098     * @param nDoubleBonds the number of double bonds in this FA.
099     * @param lipidFaBondType the bond type, e.g. ESTER.
100     */
101    public LipidSpeciesInfo(LipidLevel level, int nCarbon, int nHydroxy, int nDoubleBonds, LipidFaBondType lipidFaBondType) {
102        this(level, level.name(), -1, nCarbon, nHydroxy, nDoubleBonds, lipidFaBondType, false, ModificationsList.NONE);
103    }
104
105    @Override
106    public String buildSubstructureName(LipidLevel level) {
107        final StringBuilder sb = new StringBuilder();
108        sb.
109                append(getName()).
110                append(" ").
111                append(getNCarbon()).
112                append(":").
113                append(getNDoubleBonds());
114        if (getNHydroxy() > 0) {
115            sb.append(";").append(getNHydroxy());
116        }
117        //TODO reenable once LSI has finished modification specification
118//        if (!getModifications().isEmpty()) {
119//            sb.append("(");
120//            sb.append(getModifications().stream().map((t) -> {
121//                return (t.getLeft() == -1 ? "" : t.getLeft()) + "" + t.getRight();
122//            }).collect(Collectors.joining(",")));
123//            sb.append(")");
124//        }
125        return sb.toString();
126    }
127
128    /**
129     * Returns the element table for this species info adjusted for oxygen and
130     * hydrogen.
131     *
132     * @param numFa the number of fatty acyls to account for.
133     * @return the element table.
134     */
135    public ElementTable getElements(int numFa) {
136        ElementTable elements = super.getElements();
137        if (numFa > 0) {
138            elements.incrementBy(Element.ELEMENT_O, numFa - 1);
139            elements.decrementBy(Element.ELEMENT_H, numFa - 1);
140        }
141        return elements;
142    }
143}