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