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 */
021package org.biojava.nbio.structure;
022
023import java.io.Serializable;
024import java.util.ArrayList;
025import java.util.List;
026
027/**
028 * A simple bond -- it stores information about two atoms as well as information
029 * about its bond order.
030 *
031 * @author Jules Jacobsen <jacobsen@ebi.ac.uk>
032 * @author Ulysse Carion
033 */
034public class BondImpl implements Serializable, Bond {
035
036        private static final long serialVersionUID = 8836120946858134380L;
037        private Atom atomA;
038        private Atom atomB;
039        private int bondOrder;
040
041        /**
042         * Constructs a new bond from a pair of atoms and the bond order of the bond
043         * between them.
044         * <p>
045         * Note that by forming a bond between atoms 'A' and 'B' with this
046         * constructor, atoms 'A' and 'B' will be updated to have this bond in their
047         * list of bonds. If you do not want this automatic updating, instead use
048         * {@link #Bond(Atom, Atom, int, boolean)} with the
049         * <code>addSelfToAtoms</code> flag set to <code>false</code>.
050         *
051         * @param atomA one of the atoms in this bond
052         * @param atomB the other atom in this bond
053         * @param bondOrder the bond order of this bond
054         */
055        public BondImpl(Atom atomA, Atom atomB, int bondOrder) {
056                this(atomA, atomB, bondOrder, true);
057        }
058
059        /**
060         * Constructs a new bond from a pair of atoms and the bond order of the bond
061         * between them.
062         *
063         * @param atomA one of the atoms in this bond
064         * @param atomB the other atom in this bond
065         * @param bondOrder the bond order of this bond
066         * @param addSelfToAtoms if set to true, this bond, once created, will
067         * automatically add itself to atomA and atomB's bond lists. (If this
068         * argument is set to false, the list returned from {@link Atom#getBonds()}
069         * will not contain this bond.)
070         */
071        public BondImpl(Atom atomA, Atom atomB, int bondOrder, boolean addSelfToAtoms) {
072                this.atomA = atomA;
073                this.atomB = atomB;
074                this.bondOrder = bondOrder;
075
076                if (addSelfToAtoms) {
077                        addSelfToAtoms();
078                }
079        }
080
081        /**
082         * Adds this Bond to its atoms bond lists. If this method is not called,
083         * then the list returned from calling {@link Atom#getBonds()} will not
084         * include this bond.
085         * <p>
086         * If you created your Bond with the constructor
087         * {@link #Bond(Atom, Atom, int)}, this method has already been called for
088         * you and should not be called again.
089         */
090        // TODO first check if those bonds haven't been made already
091        private void addSelfToAtoms() {
092                List<Bond> bonds = atomA.getBonds();
093                if (bonds==null) {
094                        bonds = new ArrayList<Bond>(AtomImpl.BONDS_INITIAL_CAPACITY);
095                        atomA.setBonds(bonds);
096                }
097
098                boolean exists = false;
099                for (Bond bond : bonds) {
100                        // TODO is it equals() what we want here, or is it == ? - JD 2016-03-02
101                        if (bond.getOther(atomA).equals(atomB)) {
102                                exists = true;
103                                break;
104                        }
105                }
106                if (!exists) {
107                        atomA.addBond(this);
108                        atomB.addBond(this);
109                }
110        }
111
112        /**
113         * Gets atom 'A' of this bond. There is no meaning to which atom is 'A' and
114         * which is 'B'; the atoms are labeled 'A' or 'B' based on the order in
115         * which they are passed to this class's constructor.
116         *
117         * @see #getAtomB()
118         * @return one of the two atoms in this bond
119         */
120        @Override
121        public Atom getAtomA() {
122                return atomA;
123        }
124
125        /**
126         * Gets atom 'B' of this bond. There is no meaning to which atom is 'A' and
127         * which is 'B'; the atoms are labeled 'A' or 'B' based on the order in
128         * which they are passed to this class's constructor.
129         *
130         * @see #getAtomA()
131         * @return one of the two atoms in this bond
132         */
133        @Override
134        public Atom getAtomB() {
135                return atomB;
136        }
137
138        /**
139         * A utility method to get the other atom in a bond, given one of its atoms.
140         * If the atom passed is one of the atoms in this bond, then this method is
141         * essentially equivalent to saying
142         * <code>atom == bond.getAtomA() ? bond.getAtomB() : bond.getAtomA()</code>.
143         * <p>
144         * <i>Note:</i> Comparison of atoms in this method is done with
145         * <code>==</code>, not <code>equals</code>.
146         *
147         * @param exclude the atom of the bond to not return
148         * @throws IllegalArgumentException if the passed atom is not in this bond
149         * @return the atom in this bond that was not passed as an argument
150         */
151        @Override
152        public Atom getOther(Atom exclude) {
153                if (exclude != atomA && exclude != atomB) {
154                        throw new IllegalArgumentException(
155                                        "Atom to exclude is not in bond.");
156                }
157
158                if (exclude == atomA) {
159                        return atomB;
160                } else {
161                        return atomA;
162                }
163        }
164
165        /**
166         * Gets the bond order of this bond. A return value of '1' corresponds to a
167         * single bond, '2' to a double bond, etc.
168         *
169         * @return this bond's bond order
170         */
171        @Override
172        public int getBondOrder() {
173                return bondOrder;
174        }
175
176        /**
177         * Gets the distance between the two atoms of this bond.
178         * <p>
179         * This distance is calculated by {@link Calc#getDistance(Atom, Atom)}, but
180         * this method will suppress the empty threat of a
181         * {@link StructureException} that method makes.
182         *
183         * @return the distance between the two atoms of this bond.
184         */
185        @Override
186        public double getLength() {
187
188                return Calc.getDistance(atomA, atomB);
189
190        }
191
192        @Override
193        public String toString() {
194                return "Bond [atomA=" + atomA + ", atomB=" + atomB + ", bondOrder="
195                                + bondOrder + "]";
196        }
197
198
199
200}