001/*
002 *                    BioJava development code
003 *
004 * This code may be freely distributed and modified under the
005 * terms of the GNU Lesser General Public Licence.  This should
006 * be distributed with the code.  If you do not have a copy,
007 * see:
008 *
009 *      http://www.gnu.org/copyleft/lesser.html
010 *
011 * Copyright for this code is held jointly by the individual
012 * authors.  These should be listed in @author doc comments.
013 *
014 * For more information on the BioJava project and its aims,
015 * or to join the biojava-l mailing list, visit the home page
016 * at:
017 *
018 *      http://www.biojava.org/
019 *
020 * Created on 22.01.2007
021 *
022 */
023package org.biojava.nbio.structure;
024
025
026import org.biojava.nbio.structure.io.FileParsingParameters;
027import org.slf4j.Logger;
028import org.slf4j.LoggerFactory;
029
030import java.io.Serializable;
031import java.util.ArrayList;
032import java.util.Collections;
033import java.util.HashMap;
034import java.util.List;
035import java.util.Map;
036import java.util.Set;
037import java.util.TreeSet;
038
039/**
040 * An object to contain the info from the PDB header for a Molecule.
041 * In mmCIF dictionary, it is called an Entity. In the case of polymers it
042 * is defined as each group of sequence identical NCS-related chains
043 *
044 * Now PDB file format 3.2 aware - contains the new TAX_ID fields for the
045 * organism studied and the expression system.
046 *
047 * @author Jules Jacobsen
048 * @author Jose Duarte
049 * @author Anthony Bradley
050 * @since 1.5
051 */
052public class EntityInfo implements Serializable {
053
054        private final static Logger logger = LoggerFactory.getLogger(EntityInfo.class);
055
056
057        // TODO We could drop a lot of the stuff here that is PDB-file related (actually many PDB files don't contain many of these fields) - JD 2016-03-25
058        //     The only really essential part of a EntityInfo is the member chains and the entity_id/mol_id
059        // See also issue https://github.com/biojava/biojava/issues/219
060
061        private static final long serialVersionUID = 2991897825657586356L;
062
063        /**
064         * The list of chains that are described by this EntityInfo
065         */
066        private List<Chain> chains;
067
068        /**
069         * The Molecule identifier, called entity_id in mmCIF dictionary
070         */
071        private int molId;
072
073        /**
074         * A map to cache residue number mapping, between ResidueNumbers and index (1-based) in aligned sequences (SEQRES).
075         * Initialised lazily upon call to {@link #getAlignedResIndex(Group, Chain)}
076         * Keys are asym_ids of chains, values maps of residue numbers to indices.
077         */
078        private Map<String, Map<ResidueNumber,Integer>> chains2pdbResNums2ResSerials;
079
080        private String refChainId;
081        private String description = null;
082        private String title = null;
083        /**
084         * The type of entity (polymer, non-polymer, water)
085         */
086        private EntityType type = null;
087        private List<String> synonyms = null;
088        private List<String> ecNums = null;
089        private String engineered = null;
090        private String mutation = null;
091        private String biologicalUnit = null;
092        private String details = null;
093        private String numRes = null;
094        private String resNames = null;
095        private String headerVars = null;
096        private String synthetic = null;
097        private String fragment = null;
098        private String organismScientific = null;
099        private String organismTaxId = null;
100        private String organismCommon = null;
101        private String strain = null;
102        private String variant = null;
103        private String cellLine = null;
104        private String atcc = null;
105        private String organ = null;
106        private String tissue = null;
107        private String cell = null;
108        private String organelle = null;
109        private String secretion = null;
110        private String gene = null;
111        private String cellularLocation = null;
112        private String expressionSystem = null;
113        private String expressionSystemTaxId = null;
114        private String expressionSystemStrain = null;
115        private String expressionSystemVariant = null;
116        private String expressionSystemCellLine = null;
117        private String expressionSystemAtccNumber = null;
118        private String expressionSystemOrgan = null;
119        private String expressionSystemTissue = null;
120        private String expressionSystemCell = null;
121        private String expressionSystemOrganelle = null;
122        private String expressionSystemCellularLocation = null;
123        private String expressionSystemVectorType = null;
124        private String expressionSystemVector = null;
125        private String expressionSystemPlasmid = null;
126        private String expressionSystemGene = null;
127        private String expressionSystemOtherDetails = null;
128
129        private Long id;
130
131        public EntityInfo () {
132                chains = new ArrayList<Chain>();
133                chains2pdbResNums2ResSerials = new HashMap<String, Map<ResidueNumber,Integer>>();
134                molId = -1;
135        }
136
137        /**
138         * Constructs a new EntityInfo copying all data from the given one
139         * but not setting the Chains
140         * @param c
141         */
142        public EntityInfo (EntityInfo c) {
143
144                this.chains = new ArrayList<Chain>();
145
146                this.chains2pdbResNums2ResSerials = new HashMap<String, Map<ResidueNumber,Integer>>();
147
148                this.molId = c.molId;
149                
150                this.type = c.type;
151
152                this.refChainId = c.refChainId;
153
154                this.description = c.description;
155                this.title = c.title;
156
157                if (c.synonyms!=null) {
158                        this.synonyms = new ArrayList<String>();
159                        synonyms.addAll(c.synonyms);
160                }
161                if (c.ecNums!=null) {
162                        this.ecNums = new ArrayList<String>();
163                        ecNums.addAll(c.ecNums);
164                }
165
166                this.engineered = c.engineered;
167                this.mutation = c.mutation;
168                this.biologicalUnit = c.biologicalUnit;
169                this.details = c.details;
170
171                this.numRes = c.numRes;
172                this.resNames = c.resNames;
173
174                this.headerVars = c.headerVars;
175
176                this.synthetic = c.synthetic;
177                this.fragment = c.fragment;
178                this.organismScientific = c.organismScientific;
179                this.organismTaxId = c.organismTaxId;
180                this.organismCommon = c.organismCommon;
181                this.strain = c.strain;
182                this.variant = c.variant;
183                this.cellLine = c.cellLine;
184                this.atcc = c.atcc;
185                this.organ = c.organ;
186                this.tissue = c.tissue;
187                this.cell = c.cell;
188                this.organelle = c.organelle;
189                this.secretion = c.secretion;
190                this.gene = c.gene;
191                this.cellularLocation = c.cellularLocation;
192                this.expressionSystem = c.expressionSystem;
193                this.expressionSystemTaxId = c.expressionSystemTaxId;
194                this.expressionSystemStrain = c.expressionSystemStrain;
195                this.expressionSystemVariant = c.expressionSystemVariant;
196                this.expressionSystemCellLine = c.expressionSystemCellLine;
197                this.expressionSystemAtccNumber = c.expressionSystemAtccNumber;
198                this.expressionSystemOrgan = c.expressionSystemOrgan;
199                this.expressionSystemTissue = c.expressionSystemTissue;
200                this.expressionSystemCell = c.expressionSystemCell;
201                this.expressionSystemOrganelle = c.expressionSystemOrganelle;
202                this.expressionSystemCellularLocation = c.expressionSystemCellularLocation;
203                this.expressionSystemVectorType = c.expressionSystemVectorType;
204                this.expressionSystemVector = c.expressionSystemVector;
205                this.expressionSystemPlasmid = c.expressionSystemPlasmid;
206                this.expressionSystemGene = c.expressionSystemGene;
207                this.expressionSystemOtherDetails = c.expressionSystemOtherDetails;
208
209
210        }
211
212        @Override
213        public String toString(){
214                StringBuilder buf = new StringBuilder();
215                buf.append("EntityInfo: ").append(molId).append(" ");
216                buf.append(description==null?"(no name)":"("+description+")");
217                buf.append(" asymIds: ");
218                if (chains!=null) {
219                        for (int i=0;i<chains.size();i++) {
220                                buf.append(chains.get(i).getId());
221                                if (i!=chains.size()-1) buf.append(",");
222                        }
223                } else {
224                        buf.append("no chains");
225                }
226                return buf.toString();
227        }
228
229        /**
230         * Get the representative Chain for this EntityInfo.
231         * We choose the Chain with the first asym_id chain identifier after
232         * lexicographical sorting (case insensitive),
233         * e.g. chain A if EntityInfo is composed of chains A,B,C,D,E
234         * @return
235         */
236        public Chain getRepresentative() {
237
238                List<String> chainIds = new ArrayList<String>();
239                for (Chain chain:chains) {
240                        chainIds.add(chain.getId());
241                }
242
243                Collections.sort(chainIds, String.CASE_INSENSITIVE_ORDER);
244
245                for (Chain chain:chains) {
246                        if (chain.getId().equals(chainIds.get(0))) {
247                                return chain;
248                        }
249                }
250
251                logger.error("Could not find a representative chain for EntityInfo '{}'", this.toString());
252
253                return null;
254        }
255
256        /** get the ID used by Hibernate
257         *
258         * @return the ID used by Hibernate
259         */
260        public Long getId() {
261                return id;
262        }
263
264        /** set the ID used by Hibernate
265         *
266         * @param id
267         */
268        public void setId(Long id) {
269                this.id = id;
270        }
271
272        /**
273         * Return the list of member chain ids (asym ids) that are described by this EntityInfo,
274         * only unique chain IDs are contained in the list.
275         * Note that in the case of multimodel structures this will return just the unique
276         * chain identifiers whilst {@link #getChains()} will return a corresponding chain
277         * per model.
278         * @return the list of unique ChainIDs that are described by this EnityInfo
279         * @see #setChains(List)
280         * @see #getChains()
281         */
282        public List<String> getChainIds() {
283
284                Set<String> uniqChainIds = new TreeSet<String>();
285                for (int i=0;i<getChains().size();i++) {
286                        uniqChainIds.add(getChains().get(i).getId());
287                }
288
289                return new ArrayList<String>(uniqChainIds);
290        }
291
292        /**
293         * Given a Group g of Chain c (member of this EnityInfo) return the corresponding position in the
294         * alignment of all member sequences (1-based numbering), i.e. the index (1-based) in the SEQRES sequence.
295         * This allows for comparisons of residues belonging to different chains of the same EnityInfo (entity).
296         * <p>
297         * If {@link FileParsingParameters#setAlignSeqRes(boolean)} is not used or SEQRES not present, a mapping
298         * will not be available and this method will return {@link ResidueNumber#getSeqNum()} for all residues, which
299         * in some cases will be correctly aligned indices (when no insertion codes are
300         * used and when all chains within the entity are numbered in the same way), but
301         * in general they will be neither unique (because of insertion codes) nor aligned.
302         * </p>
303         * @param g
304         * @param c
305         * @return the aligned residue index (1 to n), if no SEQRES groups are available at all then {@link ResidueNumber#getSeqNum()}
306         * is returned as a fall-back, if the group is not found in the SEQRES groups then -1 is returned
307         * for the given group and chain
308         * @throws IllegalArgumentException if the given Chain is not a member of this EnityInfo
309         * @see {@link Chain#getSeqResGroup(int)}
310         */
311        public int getAlignedResIndex(Group g, Chain c) {
312
313                boolean contained = false;
314                for (Chain member:getChains()) {
315                        if (c.getId().equals(member.getId())) {
316                                contained = true;
317                                break;
318                        }
319                }
320                if (!contained)
321                        throw new IllegalArgumentException("Given chain with asym_id "+c.getId()+" is not a member of this entity: "+getChainIds().toString());
322
323                if (!chains2pdbResNums2ResSerials.containsKey(c.getId())) {
324                        // we do lazy initialisation of the map
325                        initResSerialsMap(c);
326                }
327                // if no seqres groups are available at all the map will be null
328                Map<ResidueNumber,Integer> map = chains2pdbResNums2ResSerials.get(c.getId());
329                int serial;
330                if (map!=null) {
331
332                        ResidueNumber resNum = g.getResidueNumber();
333                        // the resNum will be null for groups that are SEQRES only and not in ATOM,
334                        // still it can happen that a group is in ATOM in one chain but not in other of the same entity.
335                        // This is what we try to find out here (analogously to what we do in initResSerialsMap() ):
336                        if (resNum==null && c.getSeqResGroups()!=null && !c.getSeqResGroups().isEmpty()) {
337                                
338                                int index = c.getSeqResGroups().indexOf(g);
339
340                                resNum = findResNumInOtherChains(index, c);
341
342                        }
343
344                        if (resNum == null) {
345                                // still null, we really can't map
346                                serial = -1;
347                        }
348                        else {
349
350                                Integer alignedSerial = map.get(resNum);
351
352                                if (alignedSerial==null) {
353                                        // the map doesn't contain this group, something's wrong: return -1
354                                        serial = -1;
355                                } else {
356                                        serial = alignedSerial;
357                                }
358                        }
359
360                } else {
361                        // no seqres groups available we resort to using the pdb residue numbers are given
362                        serial = g.getResidueNumber().getSeqNum();
363                }
364                return serial;
365        }
366
367        private void initResSerialsMap(Chain c) {
368                if (c.getSeqResGroups()==null || c.getSeqResGroups().isEmpty()) {
369                        logger.warn("No SEQRES groups found in chain with asym_id {}, will use residue numbers as given (no insertion codes, not necessarily aligned). "
370                                        + "Make sure your structure has SEQRES records and that you use FileParsingParameters.setAlignSeqRes(true)",
371                                        c.getId());
372                        // we add a explicit null to the map so that we flag it as unavailable for this chain
373                        chains2pdbResNums2ResSerials.put(c.getId(), null);
374                        return;
375                }
376
377                Map<ResidueNumber,Integer> resNums2ResSerials = new HashMap<ResidueNumber, Integer>();
378                chains2pdbResNums2ResSerials.put(c.getId(), resNums2ResSerials);
379
380                for (int i=0;i<c.getSeqResGroups().size();i++) {
381
382                        // The seqres group will have a null residue number whenever its corresponding atom group doesn't exist
383                        // because it is missing in the electron density.
384                        // However, it can be observed in the density in other chains of the same entity,
385                        // to be complete we go and look for the residue number in other chains, so that we have a
386                        // seqres to atom mapping as complete as possible (with all known atom groups of any chain of this entity)
387
388                        ResidueNumber resNum = c.getSeqResGroup(i).getResidueNumber();
389
390                        if (resNum==null) {
391                                resNum = findResNumInOtherChains(i,c);
392                        }
393
394                        // NOTE that resNum will still be null here for cases where the residue
395                        // is missing in atom groups (not observed in density) in all chains
396                        // Thus the mapping will not be possible for residues that are only in SEQRES groups
397                        resNums2ResSerials.put(resNum, i+1);
398                }
399        }
400
401        private ResidueNumber findResNumInOtherChains(int i, Chain chain) {
402
403                // note that getChains contains all chains from all models, we'll just use first model found and skip the others
404                for (Chain c: getFirstModelChains()) {
405                        
406                        if (c == chain) continue;                       
407                        
408                        Group seqResGroup = c.getSeqResGroup(i);
409
410                        if (seqResGroup==null) {
411                                logger.warn("The SEQRES group is null for index {} in chain with asym_id {}, whilst it wasn't null in chain with asym_id {}",
412                                                 i, c.getId(), chain.getId());
413                                continue;
414                        }
415
416                        if (seqResGroup.getResidueNumber()!=null) return seqResGroup.getResidueNumber();
417
418                }
419
420                return null;
421        }
422
423        /**
424         * Return the ref chain id value.
425         * @return the RefChainID
426         * @see #setRefChainId(String)
427         */
428        public String getRefChainId() {
429                return refChainId;
430        }
431
432        /**
433         * Return the ref chain id value.
434         * @param refChainId the RefChainID
435         * @see #getRefChainId()
436         */
437        public void setRefChainId(String refChainId) {
438                this.refChainId = refChainId;
439        }
440
441        /**
442         * Return the molecule identifier, called entity_id in mmCIF dictionary.
443         * @return the molecule id
444         * @see #setMolId(int)
445         */
446        public int getMolId() {
447                return molId;
448        }
449
450        /**
451         * Set the molecule identifier, called entity_id in mmCIF dictionary.
452         * @param molId the molecule id
453         * @see #getMolId()
454         */
455        public void setMolId(int molId) {
456                this.molId = molId;
457        }
458
459        public String getDescription() {
460                return description;
461        }
462
463        public void setDescription(String molName) {
464                this.description = molName;
465        }
466
467        public String getTitle() {
468                return title;
469        }
470
471        public void setTitle(String title) {
472                this.title = title;
473        }
474
475        public List<String> getSynonyms() {
476                return synonyms;
477        }
478
479        public void setSynonyms(List<String> synonyms) {
480                this.synonyms = synonyms;
481        }
482
483        public List<String> getEcNums() {
484                return ecNums;
485        }
486
487        public void setEcNums(List<String> ecNums) {
488                this.ecNums = ecNums;
489        }
490
491        public String getEngineered() {
492                return engineered;
493        }
494
495        public void setEngineered(String engineered) {
496                this.engineered = engineered;
497        }
498
499        public String getMutation() {
500                return mutation;
501        }
502
503        public void setMutation(String mutation) {
504                this.mutation = mutation;
505        }
506
507        public String getBiologicalUnit() {
508                return biologicalUnit;
509        }
510
511        public void setBiologicalUnit(String biologicalUnit) {
512                this.biologicalUnit = biologicalUnit;
513        }
514
515        public String getDetails() {
516                return details;
517        }
518
519        public void setDetails(String details) {
520                this.details = details;
521        }
522
523        public String getNumRes() {
524                return numRes;
525        }
526
527        public void setNumRes(String numRes) {
528                this.numRes = numRes;
529        }
530
531        public String getResNames() {
532                return resNames;
533        }
534
535        public void setResNames(String resNames) {
536                this.resNames = resNames;
537        }
538
539        public String getHeaderVars() {
540                return headerVars;
541        }
542
543        public void setHeaderVars(String headerVars) {
544                this.headerVars = headerVars;
545        }
546
547        public String getSynthetic() {
548                return synthetic;
549        }
550
551        public void setSynthetic(String synthetic) {
552                this.synthetic = synthetic;
553        }
554
555        public String getFragment() {
556                return fragment;
557        }
558
559        public void setFragment(String fragment) {
560                this.fragment = fragment;
561        }
562
563        public String getOrganismScientific() {
564                return organismScientific;
565        }
566
567        public void setOrganismScientific(String organismScientific) {
568                this.organismScientific = organismScientific;
569        }
570
571        public String getOrganismTaxId() {
572                return organismTaxId;
573        }
574
575        public void setOrganismTaxId(String organismTaxId) {
576                this.organismTaxId = organismTaxId;
577        }
578
579        public String getOrganismCommon() {
580                return organismCommon;
581        }
582
583        public void setOrganismCommon(String organismCommon) {
584                this.organismCommon = organismCommon;
585        }
586
587        public String getStrain() {
588                return strain;
589        }
590
591        public void setStrain(String strain) {
592                this.strain = strain;
593        }
594
595        public String getVariant() {
596                return variant;
597        }
598
599        public void setVariant(String variant) {
600                this.variant = variant;
601        }
602
603        public String getCellLine() {
604                return cellLine;
605        }
606
607        public void setCellLine(String cellLine) {
608                this.cellLine = cellLine;
609        }
610
611        public String getAtcc() {
612                return atcc;
613        }
614
615        public void setAtcc(String atcc) {
616                this.atcc = atcc;
617        }
618
619        public String getOrgan() {
620                return organ;
621        }
622
623        public void setOrgan(String organ) {
624                this.organ = organ;
625        }
626
627        public String getTissue() {
628                return tissue;
629        }
630
631        public void setTissue(String tissue) {
632                this.tissue = tissue;
633        }
634
635        public String getCell() {
636                return cell;
637        }
638
639        public void setCell(String cell) {
640                this.cell = cell;
641        }
642
643        public String getOrganelle() {
644                return organelle;
645        }
646
647        public void setOrganelle(String organelle) {
648                this.organelle = organelle;
649        }
650
651        public String getSecretion() {
652                return secretion;
653        }
654
655        public void setSecretion(String secretion) {
656                this.secretion = secretion;
657        }
658
659        public String getGene() {
660                return gene;
661        }
662
663        public void setGene(String gene) {
664                this.gene = gene;
665        }
666
667        public String getCellularLocation() {
668                return cellularLocation;
669        }
670
671        public void setCellularLocation(String cellularLocation) {
672                this.cellularLocation = cellularLocation;
673        }
674
675        public String getExpressionSystem() {
676                return expressionSystem;
677        }
678
679        public String getExpressionSystemTaxId() {
680                return expressionSystemTaxId;
681        }
682
683        public void setExpressionSystemTaxId(String expressionSystemTaxId) {
684                this.expressionSystemTaxId = expressionSystemTaxId;
685        }
686
687        public void setExpressionSystem(String expressionSystem) {
688                this.expressionSystem = expressionSystem;
689        }
690
691        public String getExpressionSystemStrain() {
692                return expressionSystemStrain;
693        }
694
695        public void setExpressionSystemStrain(String expressionSystemStrain) {
696                this.expressionSystemStrain = expressionSystemStrain;
697        }
698
699        public String getExpressionSystemVariant() {
700                return expressionSystemVariant;
701        }
702
703        public void setExpressionSystemVariant(String expressionSystemVariant) {
704                this.expressionSystemVariant = expressionSystemVariant;
705        }
706
707        public String getExpressionSystemCellLine() {
708                return expressionSystemCellLine;
709        }
710
711        public void setExpressionSystemCellLine(String expressionSystemCellLine) {
712                this.expressionSystemCellLine = expressionSystemCellLine;
713        }
714
715        public String getExpressionSystemAtccNumber() {
716                return expressionSystemAtccNumber;
717        }
718
719        public void setExpressionSystemAtccNumber(String expressionSystemAtccNumber) {
720                this.expressionSystemAtccNumber = expressionSystemAtccNumber;
721        }
722
723        public String getExpressionSystemOrgan() {
724                return expressionSystemOrgan;
725        }
726
727        public void setExpressionSystemOrgan(String expressionSystemOrgan) {
728                this.expressionSystemOrgan = expressionSystemOrgan;
729        }
730
731        public String getExpressionSystemTissue() {
732                return expressionSystemTissue;
733        }
734
735        public void setExpressionSystemTissue(String expressionSystemTissue) {
736                this.expressionSystemTissue = expressionSystemTissue;
737        }
738
739        public String getExpressionSystemCell() {
740                return expressionSystemCell;
741        }
742
743        public void setExpressionSystemCell(String expressionSystemCell) {
744                this.expressionSystemCell = expressionSystemCell;
745        }
746
747        public String getExpressionSystemOrganelle() {
748                return expressionSystemOrganelle;
749        }
750
751        public void setExpressionSystemOrganelle(String expressionSystemOrganelle) {
752                this.expressionSystemOrganelle = expressionSystemOrganelle;
753        }
754
755        public String getExpressionSystemCellularLocation() {
756                return expressionSystemCellularLocation;
757        }
758
759        public void setExpressionSystemCellularLocation(String expressionSystemCellularLocation) {
760                this.expressionSystemCellularLocation = expressionSystemCellularLocation;
761        }
762
763        public String getExpressionSystemVectorType() {
764                return expressionSystemVectorType;
765        }
766
767        public void setExpressionSystemVectorType(String expressionSystemVectorType) {
768                this.expressionSystemVectorType = expressionSystemVectorType;
769        }
770
771        public String getExpressionSystemVector() {
772                return expressionSystemVector;
773        }
774
775        public void setExpressionSystemVector(String expressionSystemVector) {
776                this.expressionSystemVector = expressionSystemVector;
777        }
778
779        public String getExpressionSystemPlasmid() {
780                return expressionSystemPlasmid;
781        }
782
783        public void setExpressionSystemPlasmid(String expressionSystemPlasmid) {
784                this.expressionSystemPlasmid = expressionSystemPlasmid;
785        }
786
787        public String getExpressionSystemGene() {
788                return expressionSystemGene;
789        }
790
791        public void setExpressionSystemGene(String expressionSystemGene) {
792                this.expressionSystemGene = expressionSystemGene;
793        }
794
795        public String getExpressionSystemOtherDetails() {
796                return expressionSystemOtherDetails;
797        }
798
799        public void setExpressionSystemOtherDetails(String expressionSystemOtherDetails) {
800                this.expressionSystemOtherDetails = expressionSystemOtherDetails;
801        }
802
803        /**
804         * Get the list of chains that are part of this EntityInfo. Note that for multi-model
805         * structures chains from all models are returned.
806         *
807         * @return a List of Chain objects
808         */
809        public List<Chain> getChains(){
810                return this.chains;
811        }
812
813        private List<Chain> getFirstModelChains() {
814                List<Chain> firstModel = new ArrayList<>();
815                outer:
816                for (String id: getChainIds()) {
817                        for (Chain chain:chains) {
818                                if (chain.getId().equals(id)) {
819                                        firstModel.add(chain);
820                                        break outer;
821                                }
822                        }
823                }
824                return firstModel;
825        }
826        
827         /**
828          * Add new Chain to this EntityInfo
829          * @param chain
830          */
831        public void addChain(Chain chain){
832                this.chains.add(chain);
833        }
834
835        /**
836         * Set the chains for this EntityInfo
837         * @param chains
838         */
839        public void setChains(List<Chain> chains){
840                this.chains = chains;
841        }
842
843        /**
844         * Get the type of entity this EntityInfo describes.
845         * Options are polymer, non-polymer or water.
846         * @return a string describing the type of entity. (polymer, non-polymer or water).
847         */
848        public EntityType getType() {
849                return this.type;
850        }
851
852        /**
853         * Set the type of entity this EntityInfo describes.
854         * Options are polymer, non-polymer or water.
855         * @param type a string describing the type of entity. (polymer, non-polymer or water).
856         */
857        public void setType(EntityType type) {
858                this.type = type;
859        }
860}
861