1 package org.catacomb.interlish.reflect;
2
3 import org.catacomb.be.ReReferencable;
4 import org.catacomb.interlish.service.ContentLoader;
5 import org.catacomb.interlish.service.ResourceAccess;
6 import org.catacomb.interlish.structure.*;
7 import org.catacomb.report.E;
8
9
10
11
12 public class ObjectBuilder {
13
14 Constructor instantiator;
15
16
17
18 final static int UNKNOWN = 0;
19 final static int CLASS = 1;
20 final static int FACTORY = 2;
21 final static int PROVIDER = 3;
22
23 ContentLoader contentLoader;
24
25 Object wkObject;
26 String wkID;
27
28 Element workElt;
29
30
31 public ObjectBuilder(Constructor inst) {
32 instantiator = inst;
33 if (ResourceAccess.hasContentLoader()) {
34 contentLoader = ResourceAccess.getContentLoader();
35 }
36 }
37
38
39
40
41
42
43
44
45
46
47
48 public Object buildFromElement(Element elt) {
49 workElt = elt;
50 Object ret = null;
51
52 if (elt.hasAttribute("id")) {
53 wkID = elt.getAttribute("id");
54 }
55
56
57 int mode = UNKNOWN;
58
59 if (contentLoader == null ||
60 elt.hasAttribute("class") ||
61 elt.hasAttribute("package")) {
62 mode = CLASS;
63
64 } else if (contentLoader.hasFactoryFor(elt.getName())) {
65 mode = FACTORY;
66
67 } else if (contentLoader.hasProviderOf(elt.getName())) {
68 mode = PROVIDER;
69 }
70
71 if (mode == CLASS) {
72 ret = refBuildFromElement(null, elt);
73
74 } else if (mode == FACTORY) {
75 Object ospec = contentLoader.getFactoryFor(elt.getName());
76 Factory fac = (Factory)ospec;
77
78 if (fac == null) {
79 E.error(" - loader returned null factory for " + elt.getName());
80
81 } else {
82 ret = fac.make(elt.getName());
83 wkObject = ret;
84 fac.populate(ret, elt);
85
86 if (ret instanceof ReReferencable) {
87 ((ReReferencable)ret).reReference();
88 }
89 }
90
91
92 } else if (mode == PROVIDER) {
93 ret = contentLoader.getProviderOf(elt.getName());
94 wkObject = ret;
95
96
97 populate(ret, elt);
98
99 } else {
100 E.error("dont know what to do with element (no class, factory or provider) " + elt);
101 }
102
103 return ret;
104 }
105
106
107
108 private String simpleContentSerialization(Element elt) {
109 StringBuffer sb = new StringBuffer();
110 appendContent(elt, sb);
111 return sb.toString();
112 }
113
114 private void appendContent(Element topelt, StringBuffer sb) {
115 if (topelt.getText() != null) {
116 sb.append(topelt.getText());
117 }
118 if (topelt.hasElements()) {
119 for (Element elt : topelt.getElements()) {
120
121 if (elt.hasAttributes()) {
122 sb.append("\n<" + elt.getName());
123 for (Attribute att : elt.getAttributes()) {
124 sb.append(" " + att.getName() + "=\"" + att.getValue() + "\"");
125 }
126 sb.append(">");
127 } else {
128 sb.append("<" + elt.getName() + ">");
129 }
130 appendContent(elt, sb);
131 sb.append("</" + elt.getName() + ">\n");
132 }
133 }
134
135 }
136
137
138
139 public Object refBuildFromElement(Object parent, Element elt) {
140 Object ret = null;
141
142 ret = instantiator.getChildObject(parent, elt.getName(), elt.getAttributeArray());
143
144 if (ret instanceof String) {
145
146 ret = simpleContentSerialization(elt);
147
148
149 } else if (ret instanceof String[]) {
150 ret = readStringArray(elt);
151
152 } else {
153 populate(ret, elt);
154 }
155
156 return ret;
157 }
158
159
160 private String[] readStringArray(Element elt) {
161 Element[] ea = elt.getElementArray();
162 String[] ret = null;
163 if (ea == null) {
164 ret = new String[0];
165
166 } else {
167 ret = new String[ea.length];
168 for (int i = 0; i < ea.length; i++) {
169 Element sub = ea[i];
170 if (sub.getName().equals("item")) {
171 ret[i] = sub.getAttribute("value");
172 } else {
173 E.warning("wrong element type in a string array " + sub);
174 }
175 }
176 }
177 return ret;
178 }
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204 public void populate(Object target, Element elt) {
205
206 if (target instanceof ElementReader) {
207 ((ElementReader)target).populateFrom(elt);
208
209
210 } else {
211
212 if (elt.hasAttributes()) {
213
214 for (Attribute att : elt.getAttributes()) {
215 if (att.getName().equals("archive-hash")) {
216 E.deprecate();
217
218 } else {
219 instantiator.setAttributeField(target, att.getName(), att.getValue());
220 }
221 }
222 }
223
224 if (elt.hasElements()) {
225 for (Element childelt : elt.getElements()) {
226
227
228 Object child = refBuildFromElement(target, childelt);
229
230 if (child == null) {
231 E.error("got null object from element " + childelt + " " + target.getClass().getName());
232 } else {
233 instantiator.setField(target, childelt.getName(), child);
234 }
235 }
236 }
237
238
239 if (elt.hasText()) {
240 if (target instanceof BodyValued) {
241 ((BodyValued)target).setBody(elt.getText());
242 } else {
243 String ss = elt.serialize();
244 int idis = ss.indexOf("//DISABLED");
245 if (idis >= 0 && idis < 50) {
246
247 } else {
248 E.linkToWarning("nowhere to put body text: in (" +
249 target.getClass().getName() + ") may relate to " + wkID + " " + wkObject, target);
250 }
251 }
252 }
253
254 }
255
256
257
258
259
260
261 if (target instanceof ReReferencable) {
262 ((ReReferencable)target).reReference();
263 }
264 }
265
266
267 }