JAL-3518 removed unneeded override in ChimeraCommands
[jalview.git] / src / jalview / structure / StructureCommandsBase.java
1 package jalview.structure;
2
3 import java.awt.Color;
4 import java.util.ArrayList;
5 import java.util.List;
6 import java.util.Map;
7 import java.util.Map.Entry;
8
9 /**
10  * A base class holding methods useful to all classes that implement commands
11  * for structure viewers
12  * 
13  * @author gmcarstairs
14  *
15  */
16 public abstract class StructureCommandsBase implements StructureCommandsI
17 {
18   public static final String NAMESPACE_PREFIX = "jv_";
19
20   private static final String CMD_SEPARATOR = ";";
21
22   /**
23    * Returns something that separates concatenated commands
24    * 
25    * @return
26    */
27   protected String getCommandSeparator()
28   {
29     return CMD_SEPARATOR;
30   }
31
32   /**
33    * Helper method to add one contiguous range to the AtomSpec model for the given
34    * value (creating the model if necessary). As used by Jalview, {@code value} is
35    * <ul>
36    * <li>a colour, when building a 'colour structure by sequence' command</li>
37    * <li>a feature value, when building a 'set Chimera attributes from features'
38    * command</li>
39    * </ul>
40    * 
41    * @param map
42    * @param value
43    * @param model
44    * @param startPos
45    * @param endPos
46    * @param chain
47    */
48   public static final void addAtomSpecRange(Map<Object, AtomSpecModel> map,
49           Object value, String model, int startPos, int endPos,
50           String chain)
51   {
52     /*
53      * Get/initialize map of data for the colour
54      */
55     AtomSpecModel atomSpec = map.get(value);
56     if (atomSpec == null)
57     {
58       atomSpec = new AtomSpecModel();
59       map.put(value, atomSpec);
60     }
61   
62     atomSpec.addRange(model, startPos, endPos, chain);
63   }
64
65   /**
66    * Makes a structure viewer attribute name for a Jalview feature type by
67    * prefixing it with "jv_", and replacing any non-alphanumeric characters with
68    * an underscore
69    * 
70    * @param featureType
71    * @return
72    */
73   protected String makeAttributeName(String featureType)
74   {
75     StringBuilder sb = new StringBuilder();
76     if (featureType != null)
77     {
78       for (char c : featureType.toCharArray())
79       {
80         sb.append(Character.isLetterOrDigit(c) ? c : '_');
81       }
82     }
83     String attName = NAMESPACE_PREFIX + sb.toString();
84     return attName;
85   }
86
87   /**
88    * Traverse the map of colours/models/chains/positions to construct a list of
89    * 'color' commands (one per distinct colour used). The format of each command
90    * is specific to the structure viewer.
91    * <p>
92    * The default implementation returns a single command containing one command
93    * per colour, concatenated.
94    * 
95    * @param colourMap
96    * @return
97    */
98   @Override
99   public List<StructureCommandI> colourBySequence(
100           Map<Object, AtomSpecModel> colourMap)
101   {
102     List<StructureCommandI> commands = new ArrayList<>();
103     StringBuilder sb = new StringBuilder(colourMap.size() * 20);
104     boolean first = true;
105     for (Object key : colourMap.keySet())
106     {
107       Color colour = (Color) key;
108       final AtomSpecModel colourData = colourMap.get(colour);
109       StructureCommandI command = getColourCommand(colourData, colour);
110       if (!first)
111       {
112         sb.append(getCommandSeparator());
113       }
114       first = false;
115       sb.append(command.getCommand());
116     }
117
118     commands.add(new StructureCommand(sb.toString()));
119     return commands;
120   }
121
122   /**
123    * Returns a command to colour the atoms represented by {@code atomSpecModel}
124    * with the colour specified by {@code colourCode}.
125    * 
126    * @param atomSpecModel
127    * @param colour
128    * @return
129    */
130   protected StructureCommandI getColourCommand(AtomSpecModel atomSpecModel,
131           Color colour)
132   {
133     String atomSpec = getAtomSpec(atomSpecModel, false);
134     return colourResidues(atomSpec, colour);
135   }
136
137   /**
138    * Returns a command to colour the atoms described (in viewer command syntax)
139    * by {@code atomSpec} with the colour specified by {@code colourCode}
140    * 
141    * @param atomSpec
142    * @param colour
143    * @return
144    */
145   protected abstract StructureCommandI colourResidues(String atomSpec,
146           Color colour);
147
148   @Override
149   public List<StructureCommandI> colourByResidues(
150           Map<String, Color> colours)
151   {
152     List<StructureCommandI> commands = new ArrayList<>();
153     for (Entry<String, Color> entry : colours.entrySet())
154     {
155       commands.add(colourResidue(entry.getKey(), entry.getValue()));
156     }
157     return commands;
158   }
159
160   private StructureCommandI colourResidue(String resName, Color col)
161   {
162     String atomSpec = getResidueSpec(resName);
163     return colourResidues(atomSpec, col);
164   }
165
166   /**
167    * Helper method to append one start-end range to an atomspec string
168    * 
169    * @param sb
170    * @param start
171    * @param end
172    * @param chain
173    * @param firstPositionForModel
174    */
175   protected void appendRange(StringBuilder sb, int start, int end,
176           String chain, boolean firstPositionForModel, boolean isChimeraX)
177   {
178     if (!firstPositionForModel)
179     {
180       sb.append(",");
181     }
182     if (end == start)
183     {
184       sb.append(start);
185     }
186     else
187     {
188       sb.append(start).append("-").append(end);
189     }
190
191     if (!isChimeraX)
192     {
193       sb.append(".");
194       if (!" ".equals(chain))
195       {
196         sb.append(chain);
197       }
198     }
199   }
200
201   /**
202    * Returns the atom specifier meaning all occurrences of the given residue
203    * 
204    * @param residue
205    * @return
206    */
207   protected abstract String getResidueSpec(String residue);
208
209   @Override
210   public List<StructureCommandI> setAttributes(
211           Map<String, Map<Object, AtomSpecModel>> featureValues)
212   {
213     // default does nothing, override where this is implemented
214     return null;
215   }
216
217   @Override
218   public List<StructureCommandI> startNotifications(String uri)
219   {
220     return null;
221   }
222
223   @Override
224   public List<StructureCommandI> stopNotifications()
225   {
226     return null;
227   }
228
229   @Override
230   public StructureCommandI getSelectedResidues()
231   {
232     return null;
233   }
234
235   @Override
236   public StructureCommandI listResidueAttributes()
237   {
238     return null;
239   }
240
241   @Override
242   public StructureCommandI getResidueAttributes(String attName)
243   {
244     return null;
245   }
246 }