1
2
3
4
5
6
7
8
9
10
11 package com.legstar.coxb.impl.reflect;
12
13 import java.lang.reflect.Field;
14 import java.lang.reflect.Method;
15 import java.util.List;
16
17 import javax.xml.bind.annotation.XmlType;
18
19 import org.apache.commons.logging.Log;
20 import org.apache.commons.logging.LogFactory;
21
22 import com.legstar.coxb.CobolBindingException;
23 import com.legstar.coxb.CobolComplexType;
24 import com.legstar.coxb.CobolElement;
25 import com.legstar.coxb.ICobolArrayComplexBinding;
26 import com.legstar.coxb.ICobolBinaryBinding;
27 import com.legstar.coxb.ICobolBinding;
28 import com.legstar.coxb.ICobolChoiceBinding;
29 import com.legstar.coxb.ICobolComplexBinding;
30 import com.legstar.coxb.common.CComplexBinding;
31 import com.legstar.coxb.host.HostException;
32 import com.legstar.coxb.impl.CBinaryBinding;
33 import com.legstar.coxb.impl.RedefinesMap;
34 import com.legstar.coxb.util.BindingUtil;
35 import com.legstar.coxb.util.ClassUtil;
36
37
38
39
40
41
42
43
44 public class CComplexReflectBinding extends CComplexBinding {
45
46
47
48
49
50 private Object _jaxbObjectFactory;
51
52
53 private Object _jaxbObject;
54
55
56
57
58
59 private boolean _unusedJaxbObject = false;
60
61
62
63
64
65 private static final String COUNTER_SUFFIX = "Counter";
66
67
68
69
70
71 private static final String COUNTER_COBOL_SUFFIX = "--C";
72
73
74 private final Log _log = LogFactory.getLog(getClass());
75
76
77
78
79
80
81
82
83
84 public CComplexReflectBinding(final Object jaxbObjectFactory,
85 final Object jaxbObject) throws ReflectBindingException {
86
87 this(jaxbObject.getClass().getSimpleName(), jaxbObject.getClass()
88 .getSimpleName(), jaxbObject.getClass(), null, null,
89 jaxbObjectFactory);
90 _jaxbObject = jaxbObject;
91 _unusedJaxbObject = true;
92 }
93
94
95
96
97
98
99
100
101 public CComplexReflectBinding(final Object jaxbObjectFactory,
102 final Class < ? > jaxbType) throws ReflectBindingException {
103
104 this(jaxbType.getSimpleName(), jaxbType.getSimpleName(), jaxbType,
105 null, null, jaxbObjectFactory);
106 }
107
108
109
110
111
112
113
114
115
116
117
118
119 public CComplexReflectBinding(final String bindingName,
120 final String jaxbName, final Class < ? > jaxbType,
121 final CobolElement cobolAnnotations,
122 final ICobolComplexBinding parentBinding,
123 final Object jaxbObjectFactory) throws ReflectBindingException {
124
125 super(bindingName, jaxbName, jaxbType, cobolAnnotations, parentBinding);
126 _jaxbObjectFactory = jaxbObjectFactory;
127 initComplexElement(jaxbType, jaxbObjectFactory);
128 }
129
130
131
132
133
134
135
136
137
138 private void initComplexElement(final Class < ? > jaxbType,
139 final Object jaxbObjectFactory) throws ReflectBindingException {
140
141 if (_log.isDebugEnabled()) {
142 _log.debug("Initializing Complex binding for " + jaxbType);
143 }
144 XmlType xmlType = (XmlType) jaxbType.getAnnotation(XmlType.class);
145 if (xmlType == null) {
146 throw new ReflectBindingException("No jaxb annotations found in "
147 + jaxbType);
148 }
149 if (_log.isDebugEnabled()) {
150 _log.debug("Found JAXB annotations: " + xmlType.toString());
151 }
152
153
154 setValueObjectClassName(jaxbType.getName());
155 setValueObjectsFactoryClassName(jaxbObjectFactory.getClass().getName());
156
157
158
159
160
161 CobolComplexType cobolComplexType = (CobolComplexType) jaxbType
162 .getAnnotation(CobolComplexType.class);
163 if (cobolComplexType != null
164 && cobolComplexType.javaClassName() != null
165 && cobolComplexType.javaClassName().length() > 0) {
166 setValueObjectClassName(cobolComplexType.javaClassName());
167
168
169
170
171 setValueObjectsFactoryClassName(null);
172 }
173
174 initChildren(jaxbType, xmlType);
175
176 if (_log.isDebugEnabled()) {
177 _log.debug("Complex binding sucessfully initialized for: "
178 + jaxbType);
179 }
180 }
181
182
183
184
185
186
187
188
189 public void initChildren(final Class < ? > parentJaxbType,
190 final XmlType xmlType) throws ReflectBindingException {
191
192 if (_log.isDebugEnabled()) {
193 _log.debug("Initializing children of: "
194 + parentJaxbType.getSimpleName());
195 }
196
197 RedefinesMap redefinesMap = new RedefinesMap();
198
199
200 for (String prop : xmlType.propOrder()) {
201
202
203 Field field;
204 Class < ? > jaxbType;
205 try {
206 field = parentJaxbType.getDeclaredField(prop);
207 jaxbType = BindingUtil.getJavaClass(field);
208
209 } catch (SecurityException e) {
210 throw new ReflectBindingException(e);
211 } catch (NoSuchFieldException e) {
212 throw new ReflectBindingException(e);
213 } catch (CobolBindingException e) {
214 throw new ReflectBindingException(e);
215 }
216
217 ICobolBinding cobolBinding = ReflectBindingFactory.createBinding(
218 jaxbType, field, this, _jaxbObjectFactory);
219
220 if (_log.isDebugEnabled()) {
221 _log.debug("Java field " + jaxbType.getSimpleName()
222 + " bound to " + cobolBinding);
223 }
224
225
226
227
228
229 if (cobolBinding.getMaxOccurs() > 1
230 && cobolBinding.getMinOccurs() < cobolBinding
231 .getMaxOccurs()
232 && (cobolBinding.getDependingOn() == null || cobolBinding
233 .getDependingOn().length() == 0)) {
234 createDynamicCounter(cobolBinding);
235 }
236
237
238
239
240
241
242 String redefines = cobolBinding.getRedefines();
243 if (cobolBinding.isRedefined()) {
244 if (_log.isDebugEnabled()) {
245 _log.debug("Creating Choice binding for redefined Cobol element "
246 + cobolBinding.getCobolName());
247 }
248 ICobolChoiceBinding choice = ReflectBindingFactory
249 .createChoiceBinding(this, cobolBinding, redefinesMap);
250 getChildrenList().add(choice);
251
252 } else if (redefines != null && redefines.length() > 0) {
253 if (_log.isDebugEnabled()) {
254 _log.debug("Adding " + cobolBinding.getCobolName()
255 + " to Choice binding for Cobol element "
256 + redefines);
257 }
258 ICobolChoiceBinding choice = redefinesMap
259 .getChoiceElement(redefines);
260 if (choice == null) {
261 throw new ReflectBindingException("Cobol element "
262 + cobolBinding.getCobolName()
263 + " redefining unbound element " + redefines);
264 }
265
266
267
268
269 choice.addAlternative(cobolBinding);
270
271 } else {
272 getChildrenList().add(cobolBinding);
273 }
274
275 }
276 if (_log.isDebugEnabled()) {
277 _log.debug("Children sucessfully initialized for: "
278 + parentJaxbType.getSimpleName());
279 }
280 }
281
282
283
284
285
286
287
288
289
290
291 private void createDynamicCounter(final ICobolBinding cobolElement)
292 throws ReflectBindingException {
293
294 ICobolBinaryBinding counter = createDynamicCounterBinding(cobolElement);
295 storeCounter(counter);
296
297
298
299
300 cobolElement.setDependingOn(counter.getCobolName());
301
302
303
304
305
306
307
308 if (cobolElement instanceof ICobolArrayComplexBinding) {
309 ((ICobolArrayComplexBinding) cobolElement).getComplexItemBinding()
310 .setDependingOn(counter.getCobolName());
311 }
312
313 if (_log.isDebugEnabled()) {
314 _log.debug("Created depending on relationship for "
315 + cobolElement.getBindingName() + " with "
316 + counter.getCobolName());
317 }
318 }
319
320
321
322
323
324
325
326
327
328
329 private ICobolBinaryBinding createDynamicCounterBinding(
330 final ICobolBinding listBinding) throws ReflectBindingException {
331 if (_log.isDebugEnabled()) {
332 _log.debug("Creating a dynamic counter for "
333 + listBinding.getBindingName());
334 }
335 CBinaryBinding counter = new CBinaryBinding(
336 listBinding.getBindingName() + COUNTER_SUFFIX, null, null,
337 null, this);
338 counter.setCobolName(getCounterCobolName(listBinding.getCobolName()));
339 counter.setLevelNumber(listBinding.getLevelNumber());
340 counter.setUsage("BINARY");
341 counter.setPicture("9(9)");
342 counter.setByteLength(4);
343 counter.setTotalDigits(9);
344 counter.setIsODOObject(true);
345 return counter;
346 }
347
348
349
350
351
352
353
354
355
356
357 private String getCounterCobolName(final String cobolName) {
358 if (cobolName.length() < 31 - COUNTER_COBOL_SUFFIX.length()) {
359 return cobolName + COUNTER_COBOL_SUFFIX;
360 } else {
361 return cobolName.substring(0, 30 - COUNTER_COBOL_SUFFIX.length())
362 + COUNTER_COBOL_SUFFIX;
363 }
364 }
365
366
367 public void createJaxbObject() throws HostException {
368 createValueObject();
369 }
370
371
372 public void createValueObject() throws HostException {
373
374
375
376
377 if (_unusedJaxbObject && _jaxbObject != null) {
378 _unusedJaxbObject = false;
379 return;
380 }
381 _jaxbObject = BindingUtil.newJaxbObject(_jaxbObjectFactory,
382 getJaxbType().getName());
383 }
384
385
386 public void setChildrenValues() throws HostException {
387
388
389 if (_jaxbObject == null) {
390 createJaxbObject();
391 }
392
393
394 for (ICobolBinding child : getChildrenList()) {
395
396
397
398
399
400 if (!child.isBound()) {
401 continue;
402 } else {
403 Object value = ClassUtil.invokeGetProperty(_jaxbObject,
404 child.getJaxbName(), child.getJaxbType(),
405 child.getMaxOccurs());
406 if (_log.isDebugEnabled()) {
407 _log.debug("Getting value from JAXB property "
408 + child.getJaxbName() + " value=" + value);
409 }
410 child.setObjectValue(value);
411
412
413
414
415
416 if (child.getMaxOccurs() > 1
417 && child.getMinOccurs() < child.getMaxOccurs()) {
418 setCounterValue(child.getDependingOn(),
419 ((List < ? >) value).size());
420 }
421 }
422 }
423 }
424
425
426 public void setJaxbPropertyValue(final int index) throws HostException {
427 setPropertyValue(index);
428 }
429
430
431 public void setPropertyValue(final int index) throws HostException {
432
433 ICobolBinding child = getChildrenList().get(index);
434
435
436
437
438
439 if (!child.isBound()) {
440 return;
441 }
442
443
444
445 Class < ? > param = child.getJaxbType();
446 String setterName = ClassUtil.getSetterMethodName(child.getJaxbName());
447 for (Method method : _jaxbObject.getClass().getMethods()) {
448 if (method.getName().equals(setterName)) {
449 param = method.getParameterTypes()[0];
450 break;
451 }
452 }
453
454 Object value = child.getObjectValue(param);
455 if (_log.isDebugEnabled()) {
456 _log.debug("Setting value of JAXB property " + child.getJaxbName()
457 + " value=" + value);
458 }
459
460 ClassUtil.invokeSetProperty(_jaxbObject, child.getJaxbName(), value,
461 param);
462 }
463
464
465 public Object getObjectValue(final Class < ? > type) throws HostException {
466 if (type.equals(getJaxbType())) {
467 return _jaxbObject;
468 } else if (type.getName().equals(getValueObjectClassName())) {
469 return _jaxbObject;
470 } else {
471 throw new HostException("Attempt to get binding " + getJaxbName()
472 + " as an incompatible type " + type);
473 }
474 }
475
476
477 public void setObjectValue(final Object value) throws HostException {
478 if (value == null) {
479 _jaxbObject = null;
480 return;
481 }
482 if (value.getClass().equals(getJaxbType())) {
483 _jaxbObject = value;
484 } else if (value.getClass().getName().equals(getValueObjectClassName())) {
485 _jaxbObject = value;
486 } else {
487 throw new HostException("Attempt to set binding " + getJaxbName()
488 + " from an incompatible value " + value);
489 }
490 }
491
492
493
494
495 public Object getObjectFactory() {
496 return _jaxbObjectFactory;
497 }
498
499
500
501
502 public void setObjectFactory(final Object objectFactory) {
503 _jaxbObjectFactory = objectFactory;
504 }
505
506
507 public boolean isSet() {
508 return (_jaxbObject != null);
509 }
510
511 }