Skip to content

Commit e70dcbb

Browse files
sblivenjosemduarte
authored andcommitted
Introduce @CIFLabel(label="str") annotation
This replaces the short-lived getCIFLabelMap static function. It lets you associate the label directly with the applicable field
1 parent 19931b5 commit e70dcbb

File tree

4 files changed

+71
-48
lines changed

4 files changed

+71
-48
lines changed

biojava-structure/src/main/java/org/biojava/nbio/structure/io/mmcif/MMCIFFileTools.java

Lines changed: 9 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,9 @@
2222

2323

2424
import java.lang.reflect.Field;
25-
import java.lang.reflect.InvocationTargetException;
26-
import java.lang.reflect.Method;
2725
import java.util.ArrayList;
2826
import java.util.Arrays;
2927
import java.util.List;
30-
import java.util.Map;
3128

3229
import org.biojava.nbio.structure.Atom;
3330
import org.biojava.nbio.structure.Chain;
@@ -38,6 +35,7 @@
3835
import org.biojava.nbio.structure.io.FileConvert;
3936
import org.biojava.nbio.structure.io.mmcif.model.AbstractBean;
4037
import org.biojava.nbio.structure.io.mmcif.model.AtomSite;
38+
import org.biojava.nbio.structure.io.mmcif.model.CIFLabel;
4139
import org.biojava.nbio.structure.io.mmcif.model.Cell;
4240
import org.biojava.nbio.structure.io.mmcif.model.IgnoreField;
4341
import org.biojava.nbio.structure.io.mmcif.model.Symmetry;
@@ -107,27 +105,16 @@ public static String toLoopMmCifHeaderString(String categoryName, String classNa
107105
* @param o
108106
* @return
109107
*/
110-
@SuppressWarnings("unchecked")
111108
public static String toMMCIF(String categoryName, Object o) {
112109

113110
StringBuilder sb = new StringBuilder();
114111

115112
Class<?> c = o.getClass();
116113

117114

118-
// Check if the class requires any fields to be renamed
119-
Map<String,String> nameMap = null;
120-
try {
121-
Method getCIFLabelMap = c.getDeclaredMethod("getCIFLabelMap");
122-
getCIFLabelMap.setAccessible(true);
123-
nameMap = (Map<String, String>) getCIFLabelMap.invoke(null);
124-
} catch (NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | ClassCastException e1) {
125-
// no nameMap
126-
}
127-
128115
Field[] fields = getFields(c);
129-
String[] names = getFieldNames(fields, nameMap);
130-
116+
String[] names = getFieldNames(fields);
117+
131118
int maxFieldNameLength = getMaxStringLength(names);
132119

133120
for (int i=0;i<fields.length;i++) {
@@ -201,13 +188,15 @@ private static Field[] getFields(Class<?> c) {
201188
* @param nameMap
202189
* @return
203190
*/
204-
private static String[] getFieldNames(Field[] fields, Map<String, String> nameMap) {
191+
private static String[] getFieldNames(Field[] fields) {
205192
String[] names = new String[fields.length];
206193
for(int i=0;i<fields.length;i++) {
207-
fields[i].setAccessible(true);
194+
Field f = fields[i];
195+
f.setAccessible(true);
208196
String rawName = fields[i].getName();
209-
if(nameMap != null && nameMap.containsKey(rawName)) {
210-
names[i] = nameMap.get(rawName);
197+
CIFLabel cifLabel = f.getAnnotation(CIFLabel.class);
198+
if(cifLabel != null) {
199+
names[i] = cifLabel.label();
211200
} else {
212201
names[i] = rawName;
213202
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package org.biojava.nbio.structure.io.mmcif.model;
2+
3+
import java.lang.annotation.ElementType;
4+
import java.lang.annotation.Retention;
5+
import java.lang.annotation.RetentionPolicy;
6+
import java.lang.annotation.Target;
7+
8+
/**
9+
* Annotation indicating that a specific field of a bean should be mapped to
10+
* a different label
11+
* @author Spencer Bliven
12+
*
13+
*/
14+
@Target(value=ElementType.FIELD)
15+
@Retention(value=RetentionPolicy.RUNTIME)
16+
public @interface CIFLabel {
17+
String label();
18+
}

biojava-structure/src/main/java/org/biojava/nbio/structure/io/mmcif/model/Symmetry.java

Lines changed: 2 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,13 @@
2020
*/
2121
package org.biojava.nbio.structure.io.mmcif.model;
2222

23-
import java.util.Collections;
24-
import java.util.HashMap;
25-
import java.util.Map;
2623

2724
public class Symmetry extends AbstractBean {
2825

2926
String entry_id;
30-
// next 2 fields have actually hyphen between H and M i.e. H-M
31-
// but java does not allow hyphens in variable names
32-
// this will have to be solved elsewhere down the line
27+
@CIFLabel(label="space_group_name_H-M")
3328
String space_group_name_H_M;
29+
@CIFLabel(label="pdbx_full_space_group_name_H-M")
3430
String pdbx_full_space_group_name_H_M;
3531
String cell_setting;
3632
String Int_Tables_number;
@@ -72,26 +68,4 @@ public String getSpace_group_name_Hall() {
7268
public void setSpace_group_name_Hall(String space_group_name_Hall) {
7369
this.space_group_name_Hall = space_group_name_Hall;
7470
}
75-
76-
@IgnoreField
77-
private static Map<String,String> nameMap = null;
78-
/**
79-
* Map between field names and their correct mmCIF representation. For
80-
* instance, the <tt>space_group_name_H_M</tt> field corresponds to
81-
* <tt>space_group_name_H-M</tt>.
82-
*
83-
* If a field is not contained in this map, the field and the mmCIF name
84-
* match.
85-
* @return map from field names to the mmCIF name
86-
*/
87-
// Note that this function is accessed via reflection
88-
static Map<String,String> getCIFLabelMap() {
89-
if(nameMap == null) {
90-
HashMap<String,String> map = new HashMap<>();
91-
map.put("space_group_name_H_M","space_group_name_H-M");
92-
map.put("pdbx_full_space_group_name_H_M", "pdbx_full_space_group_name_H-M");
93-
nameMap = Collections.unmodifiableMap(map);
94-
}
95-
return nameMap;
96-
}
9771
}

biojava-structure/src/test/java/org/biojava/nbio/structure/io/TestMMCIFWriting.java

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,12 @@
3333
import org.biojava.nbio.structure.StructureException;
3434
import org.biojava.nbio.structure.StructureIO;
3535
import org.biojava.nbio.structure.align.util.AtomCache;
36+
import org.biojava.nbio.structure.io.mmcif.MMCIFFileTools;
3637
import org.biojava.nbio.structure.io.mmcif.MMcifParser;
3738
import org.biojava.nbio.structure.io.mmcif.SimpleMMcifConsumer;
3839
import org.biojava.nbio.structure.io.mmcif.SimpleMMcifParser;
40+
import org.biojava.nbio.structure.io.mmcif.model.CIFLabel;
41+
import org.biojava.nbio.structure.io.mmcif.model.IgnoreField;
3942
import org.junit.Test;
4043

4144
public class TestMMCIFWriting {
@@ -222,5 +225,44 @@ public void test1A2C() throws IOException, StructureException {
222225
}
223226

224227
}
228+
229+
private static class DemoBean {
230+
@IgnoreField
231+
String not_a_field;
232+
233+
@SuppressWarnings("unused")//used by reflection
234+
String default_field;
235+
236+
@CIFLabel(label="custom_label")
237+
String custom_field;
238+
239+
public void setNot_a_field(String not_a_field) {
240+
this.not_a_field = not_a_field;
241+
}
242+
public void setDefault_field(String default_field) {
243+
this.default_field = default_field;
244+
}
245+
public void setCustom_field(String custom_field) {
246+
this.custom_field = custom_field;
247+
}
248+
}
225249

250+
@Test
251+
public void testBeanAnnotations() {
252+
DemoBean bean = new DemoBean();
253+
bean.setCustom_field("custom_field");
254+
bean.setDefault_field(null);
255+
bean.setNot_a_field("not_a_field");
256+
257+
258+
// Test (1) should have custom_label (@CIFLabel)
259+
// (2) shouldn't have not_a_field (@IgnoreField)
260+
String newline = System.getProperty("line.separator");
261+
String mmcif = MMCIFFileTools.toMMCIF("_demo", bean);
262+
String expected =
263+
"_demo.default_field ?" + newline
264+
+ "_demo.custom_label custom_field" + newline
265+
+ "#" + newline;
266+
assertEquals(expected, mmcif);
267+
}
226268
}

0 commit comments

Comments
 (0)