$darkmode
DENOPTIM
DENOPTIMgson.java
Go to the documentation of this file.
1/*
2 * DENOPTIM
3 * Copyright (C) 2022 Marco Foscato <marco.foscato@uib.no>
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU Affero General Public License as published
7 * by the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Affero General Public License for more details.
14 *
15 * You should have received a copy of the GNU Affero General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19package denoptim.json;
20
21import org.openscience.cdk.interfaces.IAtomContainer;
22
23import com.google.gson.ExclusionStrategy;
24import com.google.gson.FieldAttributes;
25import com.google.gson.Gson;
26import com.google.gson.GsonBuilder;
27
28import denoptim.graph.APClass;
29import denoptim.graph.APClass.APClassDeserializer;
30import denoptim.graph.APTreeMap;
31import denoptim.graph.APTreeMap.APMapSerializer;
32import denoptim.graph.AttachmentPoint;
33import denoptim.graph.DGraph;
34import denoptim.graph.DGraph.DENOPTIMGraphDeserializer;
35import denoptim.graph.DGraph.DENOPTIMGraphSerializer;
36import denoptim.graph.Edge;
37import denoptim.graph.Edge.DENOPTIMEdgeSerializer;
38import denoptim.graph.EmptyVertex;
39import denoptim.graph.Fragment;
40import denoptim.graph.Ring;
41import denoptim.graph.Ring.DENOPTIMRingSerializer;
42import denoptim.graph.SymmetricAPs;
43import denoptim.graph.SymmetricAPs.SymmetricAPsSerializer;
44import denoptim.graph.SymmetricVertexes;
45import denoptim.graph.SymmetricVertexes.SymmetricVertexesSerializer;
46import denoptim.graph.Template;
47import denoptim.graph.Vertex;
48import denoptim.graph.Vertex.DENOPTIMVertexDeserializer;
49
53public class DENOPTIMgson
54{
55 private static DENOPTIMgson instance = null;
56
57 Gson reader;
58
59 Gson writer;
60
61//------------------------------------------------------------------------------
62
63 private DENOPTIMgson()
64 {
65 writer = new GsonBuilder()
66 .registerTypeAdapter(DGraph.class, new DENOPTIMGraphSerializer())
67 .setExclusionStrategies(new DENOPTIMExclusionStrategy())
68 // Custom serializer to make json string use AP's ID as key in the
69 // map. If this is not used, then the key.toString() is used to
70 // get a string representation of the key.
71 .registerTypeAdapter(APTreeMap.class, new APMapSerializer())
72 // Custom serializer that keeps only the IDs to vertices and
73 // APs defined in the list of vertices belonging to the graph.
74 .registerTypeAdapter(Edge.class, new DENOPTIMEdgeSerializer())
75 // Custom serialized that keeps only the IDs to vertices defined in
76 // the list of vertices belonging to the graph
77 .registerTypeAdapter(Ring.class, new DENOPTIMRingSerializer())
78 // Custom serializer to make serialisation of IAtomContainers feasible.
79 // The registerTypeHierarchyAdapter is needed because of IAtomContainer is
80 // an interface.
81 .registerTypeHierarchyAdapter(IAtomContainer.class,
83 // Custom serializer to make list of references to vertexes use IDs
84 .registerTypeAdapter(SymmetricVertexes.class,
86 // Custom serializer to make list of references to APs use IDs
87 .registerTypeAdapter(SymmetricAPs.class,
89
90 .setPrettyPrinting()
91 .create();
92
93 reader = new GsonBuilder()
94 .setExclusionStrategies(new DENOPTIMExclusionStrategyNoAPMap())
95 // Custom deserializer to dispatch to the correct subclass of Vertex
96 .registerTypeAdapter(Vertex.class,
98 // Custom deserializer takes care of converting ID-based components
99 // to references to vertices and APs
100 .registerTypeAdapter(DGraph.class, new DENOPTIMGraphDeserializer())
101 .registerTypeAdapter(APClass.class, new APClassDeserializer())
102 // Custom deserialiser build an IAtomContainer from the light-weight
103 // representations of atoms and bonds.
104 .registerTypeHierarchyAdapter(IAtomContainer.class,
106 .setPrettyPrinting()
107 .create();
108
109 /*
110 * WARNING:
111 * If you have to add a Type adapter in the reader, you should consider
112 * doing it also in the GSON reader defined in DENOPTIMVertexDeserializer.
113 */
114
115 }
116
117//------------------------------------------------------------------------------
118
119 private static DENOPTIMgson getInstance()
120 {
121 if (instance == null)
122 instance = new DENOPTIMgson();
123 return instance;
124 }
125
126//------------------------------------------------------------------------------
127
128 public static Gson getReader()
129 {
130 return getInstance().reader;
131 }
132
133//------------------------------------------------------------------------------
134
135 public static Gson getWriter() {
136 return getInstance().writer;
137 }
138
139//------------------------------------------------------------------------------
140
141 public static class DENOPTIMExclusionStrategy implements ExclusionStrategy
142 {
143 @Override
144 public boolean shouldSkipField(FieldAttributes field) {
145 // cannot serialize chemical representations:
146 // class org.openscience.cdk.Atom declares multiple JSON
147 // fields named identifier
148
149 if (field.getDeclaringClass() == AttachmentPoint.class
150 && field.getName().equals("owner")) {
151 return true;
152 }
153 if (field.getDeclaringClass() == AttachmentPoint.class
154 && field.getName().equals("user")) {
155 return true;
156 }
157 if (field.getDeclaringClass() == AttachmentPoint.class
158 && field.getName().equals("cutId")) {
159 return true;
160 }
161 if (field.getDeclaringClass() == Vertex.class
162 && field.getName().equals("owner")) {
163 return true;
164 }
165 if (field.getDeclaringClass() == Fragment.class
166 && field.getName().equals("jGraphFragIsomorphism")) {
167 return true;
168 }
169 if (field.getDeclaringClass() == Template.class
170 && field.getName().equals("mol")) {
171 return true;
172 }
173
174 return false;
175 }
176
177 @Override
178 public boolean shouldSkipClass(Class<?> clazz) {
179 return false;
180 }
181 }
182
183//------------------------------------------------------------------------------
184
186 implements ExclusionStrategy
187 {
188 @Override
189 public boolean shouldSkipField(FieldAttributes field) {
190 // cannot serialize chemical representations:
191 // class org.openscience.cdk.Atom declares multiple JSON
192 // fields named identifier
193 if (field.getDeclaringClass() == AttachmentPoint.class
194 && field.getName().equals("owner")) {
195 return true;
196 }
197 if (field.getDeclaringClass() == AttachmentPoint.class
198 && field.getName().equals("user")) {
199 return true;
200 }
201 if (field.getDeclaringClass() == AttachmentPoint.class
202 && field.getName().equals("cutId")) {
203 return true;
204 }
205 if (field.getDeclaringClass() == Vertex.class
206 && field.getName().equals("owner")) {
207 return true;
208 }
209 if (field.getDeclaringClass() == Vertex.class
210 && field.getName().equals("owner")) {
211 return true;
212 }
213 if (field.getDeclaringClass() == Fragment.class
214 && field.getName().equals("jGraphFragIsomorphism")) {
215 return true;
216 }
217 if (field.getDeclaringClass() == Fragment.class
218 && field.getName().equals("lstSymAPs")) {
219 return true;
220 }
221 if (field.getDeclaringClass() == EmptyVertex.class
222 && field.getName().equals("lstSymAPs")) {
223 return true;
224 }
225 if (field.getDeclaringClass() == Template.class
226 && field.getName().equals("lstSymAPs")) {
227 return true;
228 }
229 if (field.getDeclaringClass() == Template.class
230 && field.getName().equals("innerToOuterAPs")) {
231 return true;
232 }
233 if (field.getDeclaringClass() == Template.class
234 && field.getName().equals("innerGraph")) {
235 return true;
236 }
237 if (field.getDeclaringClass() == Template.class
238 && field.getName().equals("mol")) {
239 return true;
240 }
241 if (field.getDeclaringClass() == DGraph.class
242 && field.getName().equals("symVertices")) {
243 return true;
244 }
245
246 return false;
247 }
248
249 @Override
250 public boolean shouldSkipClass(Class<?> clazz) {
251 return false;
252 }
253 }
254
255//------------------------------------------------------------------------------
256
257}
Method that serializes this class without creating loops of references.
Definition: APTreeMap.java:56
Attachment point mapping where keys are sorted by natural ordering, i.e., by AttachmentPoint#compareT...
Definition: APTreeMap.java:43
An attachment point (AP) is a possibility to attach a Vertex onto the vertex holding the AP (i....
We expect unique IDs for vertices.
Definition: DGraph.java:6714
Container for the list of vertices and the edges that connect them.
Definition: DGraph.java:102
This class represents the edge between two vertices.
Definition: Edge.java:38
An empty vertex has the behaviors of a vertex, but has no molecular structure.
Class representing a continuously connected portion of chemical object holding attachment points.
Definition: Fragment.java:61
This class represents the closure of a ring in a spanning tree.
Definition: Ring.java:40
A collection of AttachmentPoints that are related by a relation that we call "symmetry",...
A collection of Vertexs that are related by a relation that we call "symmetry", even though this clas...
A vertex is a data structure that has an identity and holds a list of AttachmentPoints.
Definition: Vertex.java:61
Class for de/serializing DENOPTIM graphs from/to JSON format.
static DENOPTIMgson instance
static DENOPTIMgson getInstance()
Deserialisation of collections of both light-weight atoms and bonds into a CDK IAtomContainer.
Class to serialise CDK's IAtomContainer in a simplified manner.