View Javadoc
1   // ******************************************************************************
2   //
3   // Title:       Force Field X.
4   // Description: Force Field X - Software for Molecular Biophysics.
5   // Copyright:   Copyright (c) Michael J. Schnieders 2001-2025.
6   //
7   // This file is part of Force Field X.
8   //
9   // Force Field X is free software; you can redistribute it and/or modify it
10  // under the terms of the GNU General Public License version 3 as published by
11  // the Free Software Foundation.
12  //
13  // Force Field X is distributed in the hope that it will be useful, but WITHOUT
14  // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15  // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
16  // details.
17  //
18  // You should have received a copy of the GNU General Public License along with
19  // Force Field X; if not, write to the Free Software Foundation, Inc., 59 Temple
20  // Place, Suite 330, Boston, MA 02111-1307 USA
21  //
22  // Linking this library statically or dynamically with other modules is making a
23  // combined work based on this library. Thus, the terms and conditions of the
24  // GNU General Public License cover the whole combination.
25  //
26  // As a special exception, the copyright holders of this library give you
27  // permission to link this library with independent modules to produce an
28  // executable, regardless of the license terms of these independent modules, and
29  // to copy and distribute the resulting executable under terms of your choice,
30  // provided that you also meet, for each linked independent module, the terms
31  // and conditions of the license of that module. An independent module is a
32  // module which is not derived from or based on this library. If you modify this
33  // library, you may extend this exception to your version of the library, but
34  // you are not obligated to do so. If you do not wish to do so, delete this
35  // exception statement from your version.
36  //
37  // ******************************************************************************
38  package ffx.potential.bonded;
39  
40  import org.jogamp.java3d.BranchGroup;
41  
42  import javax.swing.tree.TreeNode;
43  import java.io.Serial;
44  import java.util.Enumeration;
45  import java.util.List;
46  
47  /**
48   * The Joint class contains the geometry produced by the FGroup Joiner method.
49   *
50   * @author Michael J. Schnieders
51   * @since 1.0
52   */
53  public class Joint extends MSNode {
54  
55    @Serial
56    private static final long serialVersionUID = 1L;
57  
58    /** First group forming this Joint */
59    private final MSGroup group1;
60    /** Second group forming this Joint */
61    private final MSGroup group2;
62  
63    /** Default Constructor */
64    public Joint() {
65      super("Joint");
66      group1 = group2 = null;
67    }
68  
69    /**
70     * Constructor for Joint.
71     *
72     * @param name a {@link java.lang.String} object.
73     */
74    public Joint(String name) {
75      super(name);
76      group1 = group2 = null;
77    }
78  
79    /**
80     * Constructs a Joint between Group 1 and Group 2.
81     *
82     * @param group1 a {@link ffx.potential.bonded.MSGroup} object.
83     * @param group2 a {@link ffx.potential.bonded.MSGroup} object.
84     * @param bondNode a {@link ffx.potential.bonded.MSNode} object.
85     * @param angleNode a {@link ffx.potential.bonded.MSNode} object.
86     * @param stretchBendNode a {@link ffx.potential.bonded.MSNode} object.
87     * @param ureyBradleyNode a {@link ffx.potential.bonded.MSNode} object.
88     * @param outOfPlaneNode a {@link ffx.potential.bonded.MSNode} object.
89     * @param torsionNode a {@link ffx.potential.bonded.MSNode} object.
90     * @param improperTorsionNode a {@link ffx.potential.bonded.MSNode} object.
91     * @param stretchTorsionNode a {@link ffx.potential.bonded.MSNode} object.
92     * @param angleTorsionNode a {@link ffx.potential.bonded.MSNode} object.
93     * @param piOrbitalTorsionNode a {@link ffx.potential.bonded.MSNode} object.
94     * @param torsionTorsionNode a {@link ffx.potential.bonded.MSNode} object.
95     */
96    public Joint(MSGroup group1, MSGroup group2, MSNode bondNode, MSNode angleNode,
97        MSNode stretchBendNode, MSNode ureyBradleyNode, MSNode outOfPlaneNode, MSNode torsionNode,
98        MSNode improperTorsionNode, MSNode stretchTorsionNode, MSNode angleTorsionNode,
99        MSNode piOrbitalTorsionNode, MSNode torsionTorsionNode) {
100     super(group1 + "  " + group2);
101     this.group1 = group1;
102     this.group2 = group2;
103     if (bondNode != null && bondNode.getChildCount() != 0) {
104       add(bondNode);
105     }
106     if (angleNode != null && angleNode.getChildCount() != 0) {
107       add(angleNode);
108     }
109     if (stretchBendNode != null && stretchBendNode.getChildCount() != 0) {
110       add(stretchBendNode);
111     }
112     if (ureyBradleyNode != null && ureyBradleyNode.getChildCount() != 0) {
113       add(ureyBradleyNode);
114     }
115     if (outOfPlaneNode != null && outOfPlaneNode.getChildCount() != 0) {
116       add(outOfPlaneNode);
117     }
118     if (torsionNode != null && torsionNode.getChildCount() != 0) {
119       add(torsionNode);
120     }
121     if (improperTorsionNode != null && improperTorsionNode.getChildCount() != 0) {
122       add(improperTorsionNode);
123     }
124     if (stretchTorsionNode != null && stretchTorsionNode.getChildCount() != 0) {
125       add(stretchTorsionNode);
126     }
127     if (angleTorsionNode != null && angleTorsionNode.getChildCount() != 0) {
128       add(angleTorsionNode);
129     }
130     if (piOrbitalTorsionNode != null && piOrbitalTorsionNode.getChildCount() != 0) {
131       add(piOrbitalTorsionNode);
132     }
133     if (torsionTorsionNode != null && torsionTorsionNode.getChildCount() != 0) {
134       add(torsionTorsionNode);
135     }
136     refresh(null, null, null, null, null,
137         null, null, null, null, null, null);
138   }
139 
140   /**
141    * merge
142    *
143    * @param j a {@link ffx.potential.bonded.Joint} object.
144    */
145   public void merge(Joint j) {
146     if (!((group1 == j.group1 && group2 == j.group2)
147         || (group2 == j.group1 && group1 == j.group2))) {
148       return;
149     }
150     refresh(j.getNode(Bond.class), j.getNode(Angle.class), j.getNode(StretchBend.class),
151         j.getNode(UreyBradley.class), j.getNode(OutOfPlaneBend.class), j.getNode(Torsion.class),
152         j.getNode(ImproperTorsion.class), j.getNode(StretchTorsion.class),
153         j.getNode(AngleTorsion.class), j.getNode(PiOrbitalTorsion.class),
154         j.getNode(TorsionTorsion.class));
155   }
156 
157   /**
158    * setColor
159    *
160    * @param newColorModel a {@link ffx.potential.bonded.RendererCache.ColorModel} object.
161    */
162   public void setColor(RendererCache.ColorModel newColorModel) {
163     MSNode bonds = getNode(Bond.class);
164     if (bonds == null) {
165       return;
166     }
167     for (Enumeration<TreeNode> e = bonds.children(); e.hasMoreElements(); ) {
168       Bond b = (Bond) e.nextElement();
169       b.setColor(b.getAtom(0));
170       b.setColor(b.getAtom(1));
171     }
172   }
173 
174   /** {@inheritDoc} */
175   @Override
176   public void setView(RendererCache.ViewModel newViewModel, List<BranchGroup> newShapes) {
177     MSNode bonds = getNode(Bond.class);
178     if (bonds == null) {
179       return;
180     }
181     for (Enumeration<TreeNode> e = bonds.children(); e.hasMoreElements(); ) {
182       Bond b = (Bond) e.nextElement();
183       b.setView(newViewModel, newShapes);
184     }
185   }
186 
187   /**
188    * {@inheritDoc}
189    *
190    * <p>Overridden toString method returns: "Joint: m1 Name - m2 Name"
191    */
192   @Override
193   public String toString() {
194     return getName();
195   }
196 
197   /**
198    * Refresh the Joint.
199    *
200    * @param bonds Bond node.
201    * @param angles Angle node.
202    * @param stretchBends StretchBend node.
203    * @param ureyBradleys UreyBradley node.
204    * @param outOfPlaneBends OutOfPlaneBend node.
205    * @param torsions Torsion node.
206    * @param improperTorsions ImproperTorsion node.
207    * @param stretchTorsions StretchTorsion node.
208    * @param angleTorsions AngleTorsion node.
209    * @param piOrbitalTorsions PiOrbitalTorsion node.
210    * @param torsionTorsions TorsionTorsion node.
211    */
212   private void refresh(MSNode bonds, MSNode angles, MSNode stretchBends, MSNode ureyBradleys,
213       MSNode outOfPlaneBends, MSNode torsions, MSNode improperTorsions, MSNode stretchTorsions,
214       MSNode angleTorsions, MSNode piOrbitalTorsions, MSNode torsionTorsions) {
215 
216     // Loop over all children of the Joint.
217     for (Enumeration<TreeNode> e = children(); e.hasMoreElements(); ) {
218       MSNode jointChild = (MSNode) e.nextElement();
219       if (jointChild.getChildCount() == 0) {
220         jointChild.removeFromParent();
221         continue;
222       }
223       MSNode node = (MSNode) jointChild.getChildAt(0);
224 
225       if (node instanceof Bond) {
226         addAll("Bonds", jointChild, bonds);
227         bonds = null;
228       } else if (node instanceof Angle) {
229         addAll("Angles", jointChild, angles);
230         angles = null;
231       } else if (node instanceof StretchBend) {
232         addAll("Stretch-Bends", jointChild, stretchBends);
233         stretchBends = null;
234       } else if (node instanceof UreyBradley) {
235         addAll("Urey-Bradleys", jointChild, ureyBradleys);
236         ureyBradleys = null;
237       } else if (node instanceof OutOfPlaneBend) {
238         addAll("Out-of-Plane Bends", jointChild, outOfPlaneBends);
239         outOfPlaneBends = null;
240       } else if (node instanceof Torsion) {
241         addAll("Torsional Angles", jointChild, torsions);
242         torsions = null;
243       } else if (node instanceof ImproperTorsion) {
244         addAll("Improper Torsions", jointChild, improperTorsions);
245         improperTorsions = null;
246       } else if (node instanceof StretchTorsion) {
247         addAll("Stretch-Torsions", jointChild, stretchTorsions);
248         stretchTorsions = null;
249       } else if (node instanceof AngleTorsion) {
250         addAll("Angle-Torsions", jointChild, angleTorsions);
251         angleTorsions = null;
252       } else if (node instanceof PiOrbitalTorsion) {
253         addAll("Pi-Orbital Torsions", jointChild, piOrbitalTorsions);
254         piOrbitalTorsions = null;
255       } else if (node instanceof TorsionTorsion) {
256         addAll("Torsion-Torsions", jointChild, torsionTorsions);
257         torsionTorsions = null;
258       }
259     }
260 
261     if (bonds != null) {
262       add(bonds);
263     }
264     if (angles != null) {
265       add(angles);
266     }
267     if (stretchBends != null) {
268       add(stretchBends);
269     }
270     if (ureyBradleys != null) {
271       add(ureyBradleys);
272     }
273     if (outOfPlaneBends != null) {
274       add(outOfPlaneBends);
275     }
276     if (torsions != null) {
277       add(torsions);
278     }
279     if (improperTorsions != null) {
280       add(improperTorsions);
281     }
282     if (stretchTorsions != null) {
283       add(stretchTorsions);
284     }
285     if (angleTorsions != null) {
286       add(angleTorsions);
287     }
288     if (piOrbitalTorsions != null) {
289       add(piOrbitalTorsions);
290     }
291     if (torsionTorsions != null) {
292       add(torsionTorsions);
293     }
294   }
295 
296   /**
297    * Add all the children of the node to the parent.
298    *
299    * @param name Name of the parent.
300    * @param parent Parent node.
301    * @param node Node to add.
302    */
303   private void addAll(String name, MSNode parent, MSNode node) {
304     if (node == null) {
305       return;
306     }
307     for (MSNode bond : node.getChildList()) {
308       parent.add(bond);
309     }
310     parent.setName(name + " (" + parent.getChildCount() + ")");
311   }
312 
313   /**
314    * Get the Joint node for the specified class.
315    *
316    * @param clazz The class of the bonded term to search for.
317    * @return The Joint node for the specified class.
318    */
319   private MSNode getNode(Class<? extends BondedTerm> clazz) {
320     for (Enumeration<TreeNode> e = children(); e.hasMoreElements(); ) {
321       MSNode m = (MSNode) e.nextElement();
322       TreeNode node = m.getChildAt(0);
323       if (node.getClass().equals(clazz)) {
324         return m;
325       }
326     }
327     return null;
328   }
329 
330 }