1 package be
.nikiroo
.utils
.serial
;
3 import java
.util
.HashMap
;
5 import java
.util
.Scanner
;
6 import java
.lang
.reflect
.InvocationTargetException
;
7 import java
.lang
.reflect
.Field
;
9 import be
.nikiroo
.utils
.IOUtils
;
10 import be
.nikiroo
.utils
.StringUtils
;
13 * A simple class that can accept the output of {@link Exporter} to recreate
14 * objects as they were sent to said exporter.
16 * This class requires the objects (and their potential enclosing objects) to
17 * have an empty constructor, and does not support inner classes (it does
18 * support nested classes, though).
22 public class Importer
{
25 private Importer child
;
26 private Map
<String
, Object
> map
;
28 private String currentFieldName
;
31 map
= new HashMap
<String
, Object
>();
32 map
.put("NULL", null);
35 private Importer(Map
<String
, Object
> map
) {
39 public Importer
readLine(String line
) {
42 } catch (Exception e
) {
43 throw new IllegalArgumentException(e
);
48 public Importer
read(String data
) {
50 if (data
.startsWith("ZIP:")) {
51 data
= StringUtils
.unzip64(data
.substring("ZIP:".length()));
53 Scanner scan
= new Scanner(data
);
54 scan
.useDelimiter("\n");
55 while (scan
.hasNext()) {
56 processLine(scan
.next());
59 } catch (Exception e
) {
60 throw new IllegalArgumentException(e
);
65 public boolean processLine(String line
) throws IllegalArgumentException
,
66 NoSuchFieldException
, SecurityException
, IllegalAccessException
,
67 NoSuchMethodException
, InstantiationException
, ClassNotFoundException
, InvocationTargetException
{
68 // Defer to latest child if any
70 if (child
.processLine(line
)) {
71 if (currentFieldName
!= null) {
72 setField(currentFieldName
, child
.getValue());
73 currentFieldName
= null;
81 if (line
.equals("{")) { // START: new child if needed
83 child
= new Importer(map
);
85 } else if (line
.equals("}")) { // STOP: report self to parent
87 } else if (line
.startsWith("REF ")) { // REF: create/link self
88 String ref
= line
.substring(4).split("@")[1];
89 link
= map
.containsKey(ref
);
93 me
= SerialUtils
.createObject(line
.substring(4).split("@")[0]);
96 } else { // FIELD: new field
97 if (line
.endsWith(":")) {
98 // field value is compound
99 currentFieldName
= line
.substring(0, line
.length() - 1);
101 // field value is direct
102 int pos
= line
.indexOf(":");
103 String fieldName
= line
.substring(0, pos
);
104 String encodedValue
= line
.substring(pos
+ 1);
106 value
= SerialUtils
.decode(encodedValue
);
108 // To support simple types directly:
112 setField(fieldName
, value
);
120 private void setField(String name
, Object value
)
121 throws NoSuchFieldException
, SecurityException
,
122 IllegalArgumentException
, IllegalAccessException
{
125 Field field
= me
.getClass().getDeclaredField(name
);
127 field
.setAccessible(true);
128 field
.set(me
, value
);
129 } catch (NoSuchFieldException e
) {
130 throw new NoSuchFieldException(String
.format(
131 "Field \"%s\" was not found in object of type \"%s\".",
132 name
, me
.getClass().getCanonicalName()));
136 public Object
getValue() {