1 package com.github.celldynamics.quimp.plugin;
2
3 import java.lang.reflect.Field;
4 import java.util.HashMap;
5 import java.util.Map;
6
7 import org.apache.commons.lang3.StringUtils;
8 import org.apache.commons.lang3.math.NumberUtils;
9 import org.apache.commons.lang3.reflect.FieldUtils;
10 import org.slf4j.Logger;
11 import org.slf4j.LoggerFactory;
12
13 import com.github.celldynamics.quimp.filesystem.IQuimpSerialize;
14 import com.google.gson.Gson;
15 import com.google.gson.GsonBuilder;
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63 public abstract class AbstractPluginOptions implements Cloneable, IQuimpSerialize {
64
65
66
67 public static final transient Logger LOGGER =
68 LoggerFactory.getLogger(AbstractPluginOptions.class);
69
70
71
72 public static final transient String KEY = "opts";
73
74
75
76 public static final transient int MAXITER = 512;
77
78
79
80 @EscapedPath
81 public String paramFile;
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97 public String serialize() {
98 GsonBuilder gsonBuilder = new GsonBuilder();
99 Gson gson = gsonBuilder.create();
100 String json = null;
101 Object cp = null;
102 try {
103 cp = this.clone();
104 for (Field f : FieldUtils.getFieldsListWithAnnotation(this.getClass(), EscapedPath.class)) {
105 boolean flag = f.isAccessible();
106 try {
107 f.setAccessible(true);
108 String s = (String) f.get(this);
109 EscapedPath../../com/github/celldynamics/quimp/plugin/EscapedPath.html#EscapedPath">EscapedPath annotation = (EscapedPath) f.getAnnotation(EscapedPath.class);
110 s = annotation.left() + s + annotation.right();
111 Field cpf = getField(cp.getClass(), f.getName());
112 if (cpf != null) {
113 cpf.setAccessible(true);
114 cpf.set(cp, s);
115 cpf.setAccessible(flag);
116 }
117 } catch (IllegalArgumentException | IllegalAccessException | SecurityException
118 | ClassCastException e) {
119 ;
120 } finally {
121 f.setAccessible(flag);
122 }
123 }
124 } catch (CloneNotSupportedException e1) {
125 LOGGER.debug(e1.getMessage(), e1);
126 } finally {
127 if (cp != null) {
128 ((AbstractPluginOptions) cp).beforeSerialize();
129 }
130 json = gson.toJson(cp);
131 }
132 return json;
133 }
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155 public String serialize2Macro() {
156 return escapeJsonMacro(serialize());
157
158 }
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174 @SuppressWarnings("unchecked")
175 public static <T extends AbstractPluginOptions> T deserialize(String json, T t) {
176 GsonBuilder gsonBuilder = new GsonBuilder();
177 Gson gson = gsonBuilder.create();
178 T obj = null;
179
180 obj = (T) gson.fromJson(json, t.getClass());
181 for (Field f : FieldUtils.getFieldsListWithAnnotation(obj.getClass(), EscapedPath.class)) {
182 boolean flag = f.isAccessible();
183 try {
184 f.setAccessible(true);
185 String s = (String) f.get(obj);
186 EscapedPath../../com/github/celldynamics/quimp/plugin/EscapedPath.html#EscapedPath">EscapedPath annotation = (EscapedPath) f.getAnnotation(EscapedPath.class);
187 s = StringUtils.removeStart(s, Character.toString(annotation.left()));
188 s = StringUtils.removeEnd(s, Character.toString(annotation.right()));
189 f.set(obj, s);
190 } catch (IllegalArgumentException | IllegalAccessException | SecurityException
191 | ClassCastException e) {
192 ;
193 } finally {
194 f.setAccessible(flag);
195 }
196 }
197 return obj;
198 }
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213 public static <T extends AbstractPluginOptions> T deserialize2Macro(String json, T t)
214 throws QuimpPluginException {
215 T obj = null;
216 try {
217 String jsonU = unescapeJsonMacro(json);
218 jsonU = jsonU.replaceFirst(AbstractPluginOptions.KEY + "=", "");
219 obj = deserialize(jsonU, t);
220 ((AbstractPluginOptions) obj).afterSerialize();
221 } catch (Exception e) {
222 throw new QuimpPluginException("Malformed options string (" + e.getMessage() + ")", e);
223 }
224
225 return obj;
226
227 }
228
229
230
231
232
233
234
235
236
237
238 public String escapeJsonMacro(String json) {
239 String nospaces = removeSpacesMacro(json);
240 return nospaces.replaceAll("\\\"+", "");
241 }
242
243
244
245
246
247
248
249
250
251
252
253
254 public static String removeSpacesMacro(String param) {
255 StringBuilder sb = new StringBuilder(param.length());
256 boolean outRegion = true;
257 for (int i = 0; i < param.length(); i++) {
258 char c = param.charAt(i);
259 if (outRegion == true && Character.isWhitespace(c)) {
260 continue;
261 } else {
262 sb.append(c);
263 }
264 if (c == '(') {
265 outRegion = false;
266 }
267 if (c == ')') {
268 outRegion = true;
269 }
270 }
271 return sb.toString();
272
273 }
274
275
276
277
278
279
280
281
282 public static String unescapeJsonMacro(String json) {
283 String nospaces = removeSpacesMacro(json);
284
285 final char toInsert = '"';
286 int startIndex = 0;
287 int indexOfParenthesSL = 0;
288 int indexOfParenthesSR = 0;
289 int i = 0;
290 HashMap<String, String> map = new HashMap<>();
291
292 while (true) {
293 indexOfParenthesSL = nospaces.indexOf('[', startIndex);
294 if (indexOfParenthesSL < 0) {
295 break;
296 } else {
297 startIndex = indexOfParenthesSL;
298 indexOfParenthesSR = nospaces.indexOf(']', startIndex);
299 if (indexOfParenthesSR < 0) {
300 break;
301 }
302
303 String random = Long.toHexString(Double.doubleToLongBits(Math.random()));
304 map.put(random, nospaces.substring(indexOfParenthesSL, indexOfParenthesSR + 1));
305 nospaces = nospaces.replace(map.get(random), random);
306 startIndex = indexOfParenthesSR - map.get(random).length() + random.length();
307 }
308 if (i++ > MAXITER) {
309 throw new IllegalArgumentException("Malformed options string.");
310 }
311 }
312
313
314
315 startIndex = 0;
316 int indexOfParenthes = 0;
317 int indexOfComa = 0;
318 int indexOfColon = 0;
319
320
321 while (true) {
322 indexOfColon = nospaces.indexOf(':', startIndex);
323 startIndex = indexOfColon + 1;
324 if (indexOfColon < 0) {
325 break;
326 }
327
328 if (nospaces.charAt(indexOfColon + 1) == '{') {
329 continue;
330 }
331 indexOfComa = nospaces.indexOf(',', indexOfColon);
332 indexOfParenthes = nospaces.indexOf('}', indexOfColon);
333 if (indexOfComa < 0 || indexOfParenthes < indexOfComa) {
334 indexOfComa = indexOfParenthes;
335 }
336 String sub = nospaces.substring(indexOfColon + 1, indexOfComa);
337 if (!NumberUtils.isCreatable(sub)) {
338 nospaces = new StringBuilder(nospaces).insert(indexOfColon + 1, toInsert).toString();
339 nospaces = new StringBuilder(nospaces).insert(indexOfComa + 1, toInsert).toString();
340 startIndex += sub.length();
341 }
342 if (i++ > MAXITER) {
343 throw new IllegalArgumentException("Malformed options string.");
344 }
345 }
346
347 startIndex = 0;
348 indexOfComa = 0;
349 indexOfColon = 0;
350 indexOfParenthes = 0;
351 i = 0;
352 while (true) {
353 indexOfComa = nospaces.indexOf(',', startIndex);
354 indexOfParenthes = nospaces.indexOf('{', startIndex);
355 if (indexOfParenthes >= 0 && indexOfParenthes < Math.abs(indexOfComa)) {
356 indexOfComa = indexOfParenthes;
357 if (nospaces.charAt(indexOfParenthes + 1) == '}') {
358 startIndex = indexOfParenthes + 1;
359 continue;
360 }
361 }
362 startIndex = indexOfComa + 1;
363 if (indexOfComa < 0) {
364 break;
365 }
366 indexOfColon = nospaces.indexOf(':', startIndex);
367 nospaces = new StringBuilder(nospaces).insert(indexOfComa + 1, toInsert).toString();
368 nospaces = new StringBuilder(nospaces).insert(indexOfColon + 1, toInsert).toString();
369 if (i++ > MAXITER) {
370 throw new IllegalArgumentException("Malformed options string.");
371 }
372 }
373
374
375
376 for (Map.Entry<String, String> entry : map.entrySet()) {
377 String val = entry.getValue();
378 val = val.substring(1, val.length() - 1);
379 if (val.isEmpty()) {
380 nospaces = nospaces.replace(toInsert + entry.getKey() + toInsert, entry.getValue());
381 continue;
382 }
383 String[] elements = val.split(",");
384
385 if (!NumberUtils.isCreatable(elements[0])) {
386 for (i = 0; i < elements.length; i++) {
387 elements[i] = toInsert + elements[i] + toInsert;
388 }
389 }
390
391 String ret = "[";
392 for (i = 0; i < elements.length; i++) {
393 ret = ret.concat(elements[i]).concat(",");
394 }
395 ret = ret.substring(0, ret.length() - 1).concat("]");
396 entry.setValue(ret);
397
398
399 nospaces = nospaces.replace(toInsert + entry.getKey() + toInsert, entry.getValue());
400 }
401
402 return nospaces;
403
404 }
405
406
407
408
409
410
411 @Override
412 public void beforeSerialize() {
413 }
414
415
416
417
418
419
420 @Override
421 public void afterSerialize() throws Exception {
422 }
423
424
425
426
427
428
429
430
431
432
433
434 private static Field getField(Class<?> clazz, String name) {
435 Field field = null;
436 while (clazz != null && field == null) {
437 try {
438 field = clazz.getDeclaredField(name);
439 } catch (Exception e) {
440 ;
441 }
442 clazz = clazz.getSuperclass();
443 }
444 return field;
445 }
446 }