001package org.biojava.nbio.structure.chem;
002
003import org.biojava.nbio.structure.io.cif.CifBean;
004
005import java.util.ArrayList;
006import java.util.List;
007import java.util.Objects;
008
009/**
010 * Properties of a chemical component.
011 * @author Sebastian Bittrich
012 * @since 6.0.0
013 */
014public class ChemComp implements CifBean, Comparable<ChemComp> {
015    private static final long serialVersionUID = -4736341142030215915L;
016
017    private String id;
018    private String name;
019    private String type;
020    private String pdbxType;
021    private String formula;
022    private String monNstdParentCompId;
023    private String pdbxSynonyms;
024    private int pdbxFormalCharge;
025    private String pdbxInitialDate;
026    private String pdbxModifiedDate;
027    private String pdbxAmbiguousFlag;
028    private String pdbxReleaseStatus;
029    private String pdbxReplacedBy;
030    private String pdbxReplaces;
031    private double formulaWeight;
032    private String oneLetterCode;
033    private String threeLetterCode;
034    private String pdbxModelCoordinatesDetails;
035    private String pdbxModelCoordinatesMissingFlag;
036    private String pdbxIdealCoordinatesDetails;
037    private String pdbxIdealCoordinatesMissingFlag;
038    private String pdbxModelCoordinatesDbCode;
039    private String pdbxSubcomponentList;
040    private String pdbxProcessingSite;
041    private String monNstdFlag;
042
043    private List<ChemCompDescriptor> descriptors = new ArrayList<>();
044    private List<ChemCompBond> bonds = new ArrayList<>();
045    private List<ChemCompAtom> atoms = new ArrayList<>();
046
047    // and some derived data for easier processing...
048    private ResidueType residueType;
049    private PolymerType polymerType;
050    private boolean standard;
051
052    @Override
053    public String toString(){
054        return "ChemComp " + id +
055                " " +
056                oneLetterCode +
057                " " +
058                threeLetterCode +
059                " poly:" +
060                getPolymerType() +
061                " resi:" +
062                getResidueType() +
063                (isStandard() ? " standard" : " modified") +
064                " " +
065                name +
066                " " +
067                pdbxType +
068                " " +
069                formula +
070                " parent:" +
071                monNstdParentCompId;
072    }
073
074    public boolean hasParent(){
075        String pid = monNstdParentCompId;
076        return (pid != null) && (!pid.equals("?"));
077    }
078
079    public boolean isStandard(){
080        return standard;
081    }
082
083    private void setStandardFlag(){
084        standard = ChemCompTools.isStandardChemComp(this);
085    }
086
087    public String getId() {
088        return id;
089    }
090
091    public void setId(String id) {
092        this.id = id;
093    }
094
095    public String getName() {
096        return name;
097    }
098
099    public void setName(String name) {
100        this.name = name;
101    }
102
103    public String getType() {
104        return type;
105    }
106
107    public void setType(String type) {
108        this.type = type;
109        this.residueType = ResidueType.getResidueTypeFromString(type);
110        if (residueType != null) {
111            polymerType = residueType.polymerType;
112        }
113    }
114
115    public ResidueType getResidueType() {
116        return residueType;
117    }
118
119    public void setResidueType(ResidueType residueType) {
120        this.residueType = residueType;
121    }
122
123    public PolymerType getPolymerType() {
124        return polymerType;
125    }
126
127    public void setPolymerType(PolymerType polymerType) {
128        this.polymerType = polymerType;
129    }
130
131    public String getPdbxType() {
132        return pdbxType;
133    }
134
135    public void setPdbxType(String pdbxType) {
136        this.pdbxType = pdbxType;
137    }
138
139    public String getFormula() {
140        return formula;
141    }
142
143    public void setFormula(String formula) {
144        this.formula = formula;
145    }
146
147    public String getMonNstdParentCompId() {
148        return monNstdParentCompId;
149    }
150
151    public void setMonNstdParentCompId(String monNstdParentCompId) {
152        this.monNstdParentCompId = (monNstdParentCompId == null || monNstdParentCompId.isEmpty()) ? null : monNstdParentCompId;
153        setStandardFlag();
154    }
155
156    public String getPdbxSynonyms() {
157        return pdbxSynonyms;
158    }
159
160    public void setPdbxSynonyms(String pdbxSynonyms) {
161        this.pdbxSynonyms = pdbxSynonyms;
162    }
163
164    public int getPdbxFormalCharge() {
165        return pdbxFormalCharge;
166    }
167
168    public void setPdbxFormalCharge(int pdbxFormalCharge) {
169        this.pdbxFormalCharge = pdbxFormalCharge;
170    }
171
172    public String getPdbxInitialDate() {
173        return pdbxInitialDate;
174    }
175
176    public void setPdbxInitialDate(String pdbxInitialDate) {
177        this.pdbxInitialDate = pdbxInitialDate;
178    }
179
180    public String getPdbxModifiedDate() {
181        return pdbxModifiedDate;
182    }
183
184    public void setPdbxModifiedDate(String pdbxModifiedDate) {
185        this.pdbxModifiedDate = pdbxModifiedDate;
186    }
187
188    public String getPdbxAmbiguousFlag() {
189        return pdbxAmbiguousFlag;
190    }
191
192    public void setPdbxAmbiguousFlag(String pdbxAmbiguousFlag) {
193        this.pdbxAmbiguousFlag = pdbxAmbiguousFlag;
194    }
195
196    public String getPdbxReleaseStatus() {
197        return pdbxReleaseStatus;
198    }
199
200    public void setPdbxReleaseStatus(String pdbxReleaseStatus) {
201        this.pdbxReleaseStatus = pdbxReleaseStatus;
202    }
203
204    public String getPdbxReplacedBy() {
205        return pdbxReplacedBy;
206    }
207
208    public void setPdbxReplacedBy(String pdbxReplacedBy) {
209        this.pdbxReplacedBy = pdbxReplacedBy;
210    }
211
212    public String getPdbxReplaces() {
213        return pdbxReplaces;
214    }
215
216    public void setPdbxReplaces(String pdbxReplaces) {
217        this.pdbxReplaces = pdbxReplaces;
218    }
219
220    public double getFormulaWeight() {
221        return formulaWeight;
222    }
223
224    public void setFormulaWeight(double formulaWeight) {
225        this.formulaWeight = formulaWeight;
226    }
227
228    public String getOneLetterCode() {
229        return oneLetterCode;
230    }
231
232    public void setOneLetterCode(String oneLetterCode) {
233        // backwards compatibility that treats missing olc as ?
234        this.oneLetterCode = "".equals(oneLetterCode) ? "?" : oneLetterCode;
235        setStandardFlag();
236    }
237
238    public String getThreeLetterCode() {
239        return threeLetterCode;
240    }
241
242    public void setThreeLetterCode(String threeLetterCode) {
243        this.threeLetterCode = threeLetterCode;
244    }
245
246    public String getPdbxModelCoordinatesDetails() {
247        return pdbxModelCoordinatesDetails;
248    }
249
250    public void setPdbxModelCoordinatesDetails(String pdbxModelCoordinatesDetails) {
251        this.pdbxModelCoordinatesDetails = pdbxModelCoordinatesDetails;
252    }
253
254    public String getPdbxModelCoordinatesMissingFlag() {
255        return pdbxModelCoordinatesMissingFlag;
256    }
257
258    public void setPdbxModelCoordinatesMissingFlag(String pdbxModelCoordinatesMissingFlag) {
259        this.pdbxModelCoordinatesMissingFlag = pdbxModelCoordinatesMissingFlag;
260    }
261
262    public String getPdbxIdealCoordinatesDetails() {
263        return pdbxIdealCoordinatesDetails;
264    }
265
266    public void setPdbxIdealCoordinatesDetails(String pdbxIdealCoordinatesDetails) {
267        this.pdbxIdealCoordinatesDetails = pdbxIdealCoordinatesDetails;
268    }
269
270    public String getPdbxIdealCoordinatesMissingFlag() {
271        return pdbxIdealCoordinatesMissingFlag;
272    }
273
274    public void setPdbxIdealCoordinatesMissingFlag(String pdbxIdealCoordinatesMissingFlag) {
275        this.pdbxIdealCoordinatesMissingFlag = pdbxIdealCoordinatesMissingFlag;
276    }
277
278    public String getPdbxModelCoordinatesDbCode() {
279        return pdbxModelCoordinatesDbCode;
280    }
281
282    public void setPdbxModelCoordinatesDbCode(String pdbxModelCoordinatesDbCode) {
283        this.pdbxModelCoordinatesDbCode = pdbxModelCoordinatesDbCode;
284    }
285
286    public String getPdbxSubcomponentList() {
287        return pdbxSubcomponentList;
288    }
289
290    public void setPdbxSubcomponentList(String pdbxSubcomponentList) {
291        this.pdbxSubcomponentList = pdbxSubcomponentList;
292    }
293
294    public String getPdbxProcessingSite() {
295        return pdbxProcessingSite;
296    }
297
298    public void setPdbxProcessingSite(String pdbxProcessingSite) {
299        this.pdbxProcessingSite = pdbxProcessingSite;
300    }
301
302    public String getMonNstdFlag() {
303        return monNstdFlag;
304    }
305
306    public void setMonNstdFlag(String monNstdFlag) {
307        this.monNstdFlag = monNstdFlag;
308    }
309
310    public List<ChemCompDescriptor> getDescriptors() {
311        return descriptors;
312    }
313
314    public void setDescriptors(List<ChemCompDescriptor> descriptors) {
315        this.descriptors = descriptors;
316    }
317
318    public List<ChemCompBond> getBonds() {
319        return bonds;
320    }
321
322    public void setBonds(List<ChemCompBond> bonds) {
323        this.bonds = bonds;
324    }
325
326    public List<ChemCompAtom> getAtoms() {
327        return atoms;
328    }
329
330    public void setAtoms(List<ChemCompAtom> atoms) {
331        this.atoms = atoms;
332    }
333
334    @Override
335    public int compareTo(ChemComp arg0) {
336        if (this.equals(arg0))
337            return 0;
338        return this.getId().compareTo(arg0.getId());
339    }
340
341    @Override
342    public boolean equals(Object o) {
343        if (this == o) return true;
344        if (o == null || getClass() != o.getClass()) return false;
345        ChemComp chemComp = (ChemComp) o;
346        return standard == chemComp.standard &&
347                Objects.equals(id, chemComp.id) &&
348                Objects.equals(name, chemComp.name) &&
349                Objects.equals(type, chemComp.type) &&
350                Objects.equals(pdbxType, chemComp.pdbxType) &&
351                Objects.equals(formula, chemComp.formula) &&
352                Objects.equals(monNstdParentCompId, chemComp.monNstdParentCompId) &&
353                Objects.equals(pdbxSynonyms, chemComp.pdbxSynonyms) &&
354                Objects.equals(pdbxFormalCharge, chemComp.pdbxFormalCharge) &&
355                Objects.equals(pdbxInitialDate, chemComp.pdbxInitialDate) &&
356                Objects.equals(pdbxModifiedDate, chemComp.pdbxModifiedDate) &&
357                Objects.equals(pdbxAmbiguousFlag, chemComp.pdbxAmbiguousFlag) &&
358                Objects.equals(pdbxReleaseStatus, chemComp.pdbxReleaseStatus) &&
359                Objects.equals(pdbxReplacedBy, chemComp.pdbxReplacedBy) &&
360                Objects.equals(pdbxReplaces, chemComp.pdbxReplaces) &&
361                Objects.equals(formulaWeight, chemComp.formulaWeight) &&
362                Objects.equals(oneLetterCode, chemComp.oneLetterCode) &&
363                Objects.equals(threeLetterCode, chemComp.threeLetterCode) &&
364                Objects.equals(pdbxModelCoordinatesDetails, chemComp.pdbxModelCoordinatesDetails) &&
365                Objects.equals(pdbxModelCoordinatesMissingFlag, chemComp.pdbxModelCoordinatesMissingFlag) &&
366                Objects.equals(pdbxIdealCoordinatesDetails, chemComp.pdbxIdealCoordinatesDetails) &&
367                Objects.equals(pdbxIdealCoordinatesMissingFlag, chemComp.pdbxIdealCoordinatesMissingFlag) &&
368                Objects.equals(pdbxModelCoordinatesDbCode, chemComp.pdbxModelCoordinatesDbCode) &&
369                Objects.equals(pdbxSubcomponentList, chemComp.pdbxSubcomponentList) &&
370                Objects.equals(pdbxProcessingSite, chemComp.pdbxProcessingSite) &&
371                Objects.equals(monNstdFlag, chemComp.monNstdFlag) &&
372                Objects.equals(descriptors, chemComp.descriptors) &&
373                Objects.equals(bonds, chemComp.bonds) &&
374                Objects.equals(atoms, chemComp.atoms) &&
375                residueType == chemComp.residueType &&
376                polymerType == chemComp.polymerType;
377    }
378
379    @Override
380    public int hashCode() {
381        return Objects.hash(id, name, type, pdbxType, formula, monNstdParentCompId, pdbxSynonyms, pdbxFormalCharge, pdbxInitialDate, pdbxModifiedDate, pdbxAmbiguousFlag, pdbxReleaseStatus, pdbxReplacedBy, pdbxReplaces, formulaWeight, oneLetterCode, threeLetterCode, pdbxModelCoordinatesDetails, pdbxModelCoordinatesMissingFlag, pdbxIdealCoordinatesDetails, pdbxIdealCoordinatesMissingFlag, pdbxModelCoordinatesDbCode, pdbxSubcomponentList, pdbxProcessingSite, monNstdFlag, descriptors, bonds, atoms, residueType, polymerType, standard);
382    }
383
384    /**
385     * Creates a new instance of the dummy empty ChemComp.
386     * @return a ChemComp
387     */
388    public static ChemComp getEmptyChemComp() {
389        ChemComp comp = new ChemComp();
390
391        comp.setOneLetterCode("?");
392        comp.setThreeLetterCode("???"); // Main signal for isEmpty()
393        comp.setPolymerType(PolymerType.unknown);
394        comp.setResidueType(ResidueType.atomn);
395        return comp;
396    }
397
398    /**
399     * Indicates whether this compound was created with
400     * @return a boolean
401     */
402    public boolean isEmpty() {
403        // Is this the best flag for it being empty?
404        return id == null || getThreeLetterCode() == null || getThreeLetterCode().equals("???");
405    }
406}