1 package org.opendaylight.controller.sal.binding.dom.serializer.impl;
3 import java.lang.ref.WeakReference;
4 import java.lang.reflect.Field;
5 import java.util.AbstractMap.SimpleEntry;
6 import java.util.ArrayList;
7 import java.util.Collection;
8 import java.util.Collections;
9 import java.util.HashMap;
10 import java.util.HashSet;
11 import java.util.Iterator;
12 import java.util.List;
14 import java.util.Map.Entry;
15 import java.util.Objects;
16 import java.util.concurrent.ConcurrentHashMap;
17 import java.util.concurrent.ConcurrentMap;
19 import java.util.WeakHashMap;
21 import org.opendaylight.controller.sal.binding.dom.serializer.api.AugmentationCodec;
22 import org.opendaylight.controller.sal.binding.dom.serializer.api.ChoiceCaseCodec;
23 import org.opendaylight.controller.sal.binding.dom.serializer.api.ChoiceCodec;
24 import org.opendaylight.controller.sal.binding.dom.serializer.api.CodecRegistry;
25 import org.opendaylight.controller.sal.binding.dom.serializer.api.DataContainerCodec;
26 import org.opendaylight.controller.sal.binding.dom.serializer.api.DomCodec;
27 import org.opendaylight.controller.sal.binding.dom.serializer.api.IdentifierCodec;
28 import org.opendaylight.controller.sal.binding.dom.serializer.api.InstanceIdentifierCodec;
29 import org.opendaylight.controller.sal.binding.dom.serializer.api.ValueWithQName;
30 import org.opendaylight.controller.sal.core.api.model.SchemaServiceListener;
31 import org.opendaylight.yangtools.binding.generator.util.ReferencedTypeImpl;
32 import org.opendaylight.yangtools.binding.generator.util.Types;
33 import org.opendaylight.yangtools.concepts.Delegator;
34 import org.opendaylight.yangtools.concepts.Identifiable;
35 import org.opendaylight.yangtools.yang.binding.Augmentable;
36 import org.opendaylight.yangtools.yang.binding.Augmentation;
37 import org.opendaylight.yangtools.yang.binding.BindingCodec;
38 import org.opendaylight.yangtools.yang.binding.DataContainer;
39 import org.opendaylight.yangtools.yang.binding.Identifier;
40 import org.opendaylight.yangtools.yang.common.QName;
41 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
42 import org.opendaylight.yangtools.yang.data.api.Node;
43 import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
44 import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
45 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
46 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
47 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
48 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
49 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
50 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
51 import org.slf4j.Logger;
52 import org.slf4j.LoggerFactory;
54 import static com.google.common.base.Preconditions.*;
55 import static org.opendaylight.controller.sal.binding.dom.serializer.impl.IntermediateMapping.*;
57 import org.opendaylight.yangtools.sal.binding.generator.impl.ModuleContext;
58 import org.opendaylight.yangtools.sal.binding.model.api.ConcreteType;
59 import org.opendaylight.yangtools.sal.binding.model.api.Type;
60 import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTypeBuilder;
61 import org.opendaylight.yangtools.yang.model.api.Module;
62 import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil;
64 public class LazyGeneratedCodecRegistry implements //
66 SchemaServiceListener, //
69 private final static Logger LOG = LoggerFactory.getLogger(LazyGeneratedCodecRegistry.class);
70 private final static LateMixinCodec NOT_READY_CODEC = new LateMixinCodec();
72 private final InstanceIdentifierCodec instanceIdentifierCodec = new InstanceIdentifierCodecImpl(this);
74 private TransformerGenerator generator;
76 // Concrete class to codecs
77 private Map<Class<?>, DataContainerCodec<?>> containerCodecs = new WeakHashMap<>();
78 private Map<Class<?>, IdentifierCodec<?>> identifierCodecs = new WeakHashMap<>();
79 private Map<Class<?>, ChoiceCodecImpl<?>> choiceCodecs = new WeakHashMap<>();
80 private Map<Class<?>, ChoiceCaseCodecImpl<?>> caseCodecs = new WeakHashMap<>();
81 private Map<Class<?>, AugmentableCompositeCodec> augmentableCodecs = new WeakHashMap<>();
83 /** Binding type to encountered classes mapping **/
84 @SuppressWarnings("rawtypes")
85 Map<Type, WeakReference<Class>> typeToClass = new ConcurrentHashMap<>();
87 @SuppressWarnings("rawtypes")
88 private ConcurrentMap<Type, ChoiceCaseCodecImpl> typeToCaseNodes = new ConcurrentHashMap<>();
90 private CaseClassMapFacade classToCaseRawCodec = new CaseClassMapFacade();
92 Map<SchemaPath, GeneratedTypeBuilder> pathToType = new ConcurrentHashMap<>();
94 private SchemaContext currentSchema;
96 public TransformerGenerator getGenerator() {
100 public void setGenerator(TransformerGenerator generator) {
101 this.generator = generator;
105 public InstanceIdentifierCodec getInstanceIdentifierCodec() {
106 return instanceIdentifierCodec;
110 public <T extends Augmentation<?>> AugmentationCodec<T> getCodecForAugmentation(Class<T> object) {
111 // TODO Auto-generated method stub
116 public Class<?> getClassForPath(List<QName> names) {
117 DataSchemaNode node = getSchemaNode(names);
118 SchemaPath path = node.getPath();
119 GeneratedTypeBuilder type = pathToType.get(path);
120 ReferencedTypeImpl typeref = new ReferencedTypeImpl(type.getPackageName(), type.getName());
121 @SuppressWarnings("rawtypes")
122 WeakReference<Class> weakRef = typeToClass.get(typeref);
123 return weakRef.get();
127 public IdentifierCodec<?> getKeyCodecForPath(List<QName> names) {
128 @SuppressWarnings("unchecked")
129 Class<? extends Identifiable<?>> cls = (Class<? extends Identifiable<?>>) getClassForPath(names);
130 return getIdentifierCodecForIdentifiable(cls);
134 public <T extends DataContainer> DataContainerCodec<T> getCodecForDataObject(Class<T> type) {
135 @SuppressWarnings("unchecked")
136 DataContainerCodec<T> ret = (DataContainerCodec<T>) containerCodecs.get(type);
140 Class<? extends BindingCodec<Map<QName, Object>, Object>> newType = generator.transformerFor(type);
141 BindingCodec<Map<QName, Object>, Object> rawCodec = newInstanceOf(newType);
142 DataContainerCodecImpl<T> newWrapper = new DataContainerCodecImpl<>(rawCodec);
143 containerCodecs.put(type, newWrapper);
148 @SuppressWarnings("rawtypes")
149 public void bindingClassEncountered(Class cls) {
150 ConcreteType typeRef = Types.typeForClass(cls);
151 WeakReference<Class> weakRef = new WeakReference<>(cls);
152 typeToClass.put(typeRef, weakRef);
155 private DataSchemaNode getSchemaNode(List<QName> path) {
156 QName firstNode = path.get(0);
157 DataNodeContainer previous = currentSchema.findModuleByNamespaceAndRevision(firstNode.getNamespace(),
158 firstNode.getRevision());
159 Iterator<QName> iterator = path.iterator();
160 while (iterator.hasNext()) {
161 QName arg = iterator.next();
162 DataSchemaNode currentNode = previous.getDataChildByName(arg);
163 if (currentNode == null && previous instanceof DataNodeContainer) {
164 currentNode = searchInChoices(previous, arg);
166 if (currentNode instanceof DataNodeContainer) {
167 previous = (DataNodeContainer) currentNode;
168 } else if (currentNode instanceof LeafSchemaNode || currentNode instanceof LeafListSchemaNode) {
169 checkState(!iterator.hasNext(), "Path tries to nest inside leaf node.");
173 return (DataSchemaNode) previous;
176 private DataSchemaNode searchInChoices(DataNodeContainer node, QName arg) {
177 Set<DataSchemaNode> children = node.getChildNodes();
178 for (DataSchemaNode child : children) {
179 if (child instanceof ChoiceNode) {
180 ChoiceNode choiceNode = (ChoiceNode) child;
181 DataSchemaNode potential = searchInCases(choiceNode, arg);
182 if (potential != null) {
190 private DataSchemaNode searchInCases(ChoiceNode choiceNode, QName arg) {
191 Set<ChoiceCaseNode> cases = choiceNode.getCases();
192 for (ChoiceCaseNode caseNode : cases) {
193 DataSchemaNode node = caseNode.getDataChildByName(arg);
201 private <T> T newInstanceOf(Class<?> newType) {
203 @SuppressWarnings("unchecked")
204 T ret = (T) newType.newInstance();
206 } catch (InstantiationException e) {
207 throw new IllegalStateException(e);
208 } catch (IllegalAccessException e) {
209 throw new IllegalStateException(e);
214 public <T extends Identifiable<?>> IdentifierCodec<?> getIdentifierCodecForIdentifiable(Class<T> type) {
215 IdentifierCodec<?> obj = identifierCodecs.get(type);
219 Class<? extends BindingCodec<Map<QName, Object>, Object>> newCodec = generator
220 .keyTransformerForIdentifiable(type);
221 BindingCodec<Map<QName, Object>, Object> newInstance;
222 newInstance = newInstanceOf(newCodec);
223 IdentifierCodecImpl<?> newWrapper = new IdentifierCodecImpl<>(newInstance);
224 identifierCodecs.put(type, newWrapper);
229 public void onCodecCreated(Class<?> cls) {
230 CodecMapping.setIdentifierCodec(cls, instanceIdentifierCodec);
234 public <T extends Identifier<?>> IdentifierCodec<T> getCodecForIdentifier(Class<T> object) {
235 @SuppressWarnings("unchecked")
236 IdentifierCodec<T> obj = (IdentifierCodec<T>) identifierCodecs.get(object);
240 Class<? extends BindingCodec<Map<QName, Object>, Object>> newCodec = generator
241 .keyTransformerForIdentifier(object);
242 BindingCodec<Map<QName, Object>, Object> newInstance;
243 newInstance = newInstanceOf(newCodec);
244 IdentifierCodecImpl<T> newWrapper = new IdentifierCodecImpl<>(newInstance);
245 identifierCodecs.put(object, newWrapper);
249 @SuppressWarnings("rawtypes")
250 public ChoiceCaseCodecImpl getCaseCodecFor(Class caseClass) {
251 ChoiceCaseCodecImpl<?> potential = caseCodecs.get(caseClass);
252 if (potential != null) {
255 ConcreteType typeref = Types.typeForClass(caseClass);
256 ChoiceCaseCodecImpl caseCodec = typeToCaseNodes.get(typeref);
258 @SuppressWarnings("unchecked")
259 Class<? extends BindingCodec> newCodec = generator.caseCodecFor(caseClass, caseCodec.schema);
260 BindingCodec newInstance = newInstanceOf(newCodec);
261 caseCodec.setDelegate(newInstance);
262 caseCodecs.put(caseClass, caseCodec);
264 for (Entry<Class<?>, ChoiceCodecImpl<?>> choice : choiceCodecs.entrySet()) {
265 if (choice.getKey().isAssignableFrom(caseClass)) {
266 choice.getValue().cases.put(caseClass, caseCodec);
272 public void onModuleContextAdded(SchemaContext schemaContext, Module module, ModuleContext context) {
273 pathToType.putAll(context.getChildNodes());
275 captureCases(context.getCases(), schemaContext);
278 private void captureCases(Map<SchemaPath, GeneratedTypeBuilder> cases, SchemaContext module) {
279 for (Entry<SchemaPath, GeneratedTypeBuilder> caseNode : cases.entrySet()) {
280 ReferencedTypeImpl typeref = new ReferencedTypeImpl(caseNode.getValue().getPackageName(), caseNode
281 .getValue().getName());
282 ChoiceCaseNode node = (ChoiceCaseNode) SchemaContextUtil.findDataSchemaNode(module, caseNode.getKey());
284 LOG.error("YANGTools Bug: SchemaNode for {}, with path {} was not found in context.",typeref.getFullyQualifiedName(), caseNode.getKey());
288 @SuppressWarnings("rawtypes")
289 ChoiceCaseCodecImpl value = new ChoiceCaseCodecImpl(node);
290 typeToCaseNodes.putIfAbsent(typeref, value);
295 public void onGlobalContextUpdated(SchemaContext context) {
296 currentSchema = context;
299 @SuppressWarnings({ "unchecked", "rawtypes" })
301 public void onChoiceCodecCreated(Class<?> choiceClass,
302 Class<? extends BindingCodec<Map<QName, Object>, Object>> choiceCodec) {
303 ChoiceCodec<?> oldCodec = choiceCodecs.get(choiceClass);
304 checkState(oldCodec == null);
305 BindingCodec<Map<QName, Object>, Object> delegate = newInstanceOf(choiceCodec);
306 ChoiceCodecImpl<?> newCodec = new ChoiceCodecImpl(delegate);
307 choiceCodecs.put(choiceClass, newCodec);
308 CodecMapping.setClassToCaseMap(choiceCodec, (Map<Class, BindingCodec>) classToCaseRawCodec);
309 CodecMapping.setCompositeNodeToCaseMap(choiceCodec, newCodec.getCompositeToCase());
314 public void onValueCodecCreated(Class<?> valueClass, Class<?> valueCodec) {
315 // TODO Auto-generated method stub
320 public void onCaseCodecCreated(Class<?> choiceClass,
321 Class<? extends BindingCodec<Map<QName, Object>, Object>> choiceCodec) {
322 // TODO Auto-generated method stub
327 public void onDataContainerCodecCreated(Class<?> dataClass,
328 Class<? extends BindingCodec<Map<QName, Object>, Object>> dataCodec) {
329 if (Augmentable.class.isAssignableFrom(dataClass)) {
330 AugmentableCompositeCodec augmentableCodec = getAugmentableCodec(dataClass);
331 CodecMapping.setAugmentationCodec(dataCodec, augmentableCodec);
336 private AugmentableCompositeCodec getAugmentableCodec(Class<?> dataClass) {
337 AugmentableCompositeCodec ret = augmentableCodecs.get(dataClass);
341 ret = new AugmentableCompositeCodec(dataClass);
342 augmentableCodecs.put(dataClass, ret);
346 private static abstract class IntermediateCodec<T> implements //
347 DomCodec<T>, Delegator<BindingCodec<Map<QName, Object>, Object>> {
349 private final BindingCodec<Map<QName, Object>, Object> delegate;
352 public BindingCodec<Map<QName, Object>, Object> getDelegate() {
356 public IntermediateCodec(BindingCodec<Map<QName, Object>, Object> delegate) {
357 this.delegate = delegate;
361 public Node<?> serialize(ValueWithQName<T> input) {
362 Map<QName, Object> intermediateOutput = delegate.serialize(input);
363 return toNode(intermediateOutput);
367 private static class IdentifierCodecImpl<T extends Identifier<?>> //
368 extends IntermediateCodec<T> //
369 implements IdentifierCodec<T> {
371 public IdentifierCodecImpl(BindingCodec<Map<QName, Object>, Object> delegate) {
376 public ValueWithQName<T> deserialize(Node<?> input) {
377 QName qname = input.getNodeType();
378 @SuppressWarnings("unchecked")
379 T value = (T) getDelegate().deserialize((Map<QName, Object>) input);
380 return new ValueWithQName<T>(qname, value);
384 public CompositeNode serialize(ValueWithQName<T> input) {
385 return (CompositeNode) super.serialize(input);
389 private static class DataContainerCodecImpl<T extends DataContainer> //
390 extends IntermediateCodec<T> //
391 implements DataContainerCodec<T> {
393 public DataContainerCodecImpl(BindingCodec<Map<QName, Object>, Object> delegate) {
398 public ValueWithQName<T> deserialize(Node<?> input) {
402 QName qname = input.getNodeType();
403 @SuppressWarnings("unchecked")
404 T value = (T) getDelegate().deserialize((Map<QName, Object>) input);
405 return new ValueWithQName<T>(qname, value);
409 public CompositeNode serialize(ValueWithQName<T> input) {
410 return (CompositeNode) super.serialize(input);
414 @SuppressWarnings("rawtypes")
415 private static class ChoiceCaseCodecImpl<T extends DataContainer> implements ChoiceCaseCodec<T>, //
416 Delegator<BindingCodec> {
417 private final boolean augmenting;
418 private BindingCodec delegate;
420 private final Set<String> validNames;
421 private final Set<QName> validQNames;
422 private ChoiceCaseNode schema;
424 public ChoiceCaseCodecImpl(ChoiceCaseNode caseNode) {
425 this.delegate = NOT_READY_CODEC;
426 this.schema = caseNode;
427 validNames = new HashSet<>();
428 validQNames = new HashSet<>();
429 for (DataSchemaNode node : caseNode.getChildNodes()) {
430 QName qname = node.getQName();
431 validQNames.add(qname);
432 validNames.add(qname.getLocalName());
434 augmenting = caseNode.isAugmenting();
438 public ValueWithQName<T> deserialize(Node<?> input) {
439 throw new UnsupportedOperationException("Direct invocation of this codec is not allowed.");
443 public CompositeNode serialize(ValueWithQName<T> input) {
444 throw new UnsupportedOperationException("Direct invocation of this codec is not allowed.");
447 public BindingCodec getDelegate() {
451 public void setDelegate(BindingCodec delegate) {
452 this.delegate = delegate;
455 public ChoiceCaseNode getSchema() {
460 public boolean isAcceptable(Node<?> input) {
461 if (false == (input instanceof CompositeNode)) {
463 return checkAugmenting((CompositeNode) input);
465 return checkLocal((CompositeNode) input);
471 private boolean checkLocal(CompositeNode input) {
472 QName parent = input.getNodeType();
473 for (Node<?> childNode : input.getChildren()) {
474 QName child = childNode.getNodeType();
475 if (false == Objects.equals(parent.getNamespace(), child.getNamespace())) {
478 if (false == Objects.equals(parent.getRevision(), child.getRevision())) {
481 if (validNames.contains(child.getLocalName())) {
488 private boolean checkAugmenting(CompositeNode input) {
489 for (Node<?> child : input.getChildren()) {
490 if (validQNames.contains(child.getNodeType())) {
498 private static class ChoiceCodecImpl<T> implements ChoiceCodec<T> {
500 private final BindingCodec<Map<QName, Object>, Object> delegate;
502 @SuppressWarnings("rawtypes")
503 private final Map<Class, ChoiceCaseCodecImpl<?>> cases = new WeakHashMap<>();
505 private final CaseCompositeNodeMapFacade CompositeToCase;
507 public ChoiceCodecImpl(BindingCodec<Map<QName, Object>, Object> delegate) {
508 this.delegate = delegate;
509 this.CompositeToCase = new CaseCompositeNodeMapFacade(cases);
513 public ValueWithQName<T> deserialize(Node<?> input) {
514 throw new UnsupportedOperationException("Direct invocation of this codec is not allowed.");
518 public Node<?> serialize(ValueWithQName<T> input) {
519 throw new UnsupportedOperationException("Direct invocation of this codec is not allowed.");
522 public CaseCompositeNodeMapFacade getCompositeToCase() {
523 return CompositeToCase;
526 public Map<Class, ChoiceCaseCodecImpl<?>> getCases() {
530 public BindingCodec<Map<QName, Object>, Object> getDelegate() {
536 @SuppressWarnings("rawtypes")
537 private class CaseClassMapFacade extends MapFacadeBase {
540 public Set<java.util.Map.Entry<Class, BindingCodec<Object, Object>>> entrySet() {
545 public BindingCodec get(Object key) {
546 if (key instanceof Class) {
547 Class cls = (Class) key;
548 bindingClassEncountered(cls);
549 ChoiceCaseCodecImpl caseCodec = getCaseCodecFor(cls);
550 return caseCodec.getDelegate();
556 @SuppressWarnings("rawtypes")
557 private static class CaseCompositeNodeMapFacade extends MapFacadeBase<CompositeNode> {
559 final Map<Class, ChoiceCaseCodecImpl<?>> choiceCases;
561 public CaseCompositeNodeMapFacade(Map<Class, ChoiceCaseCodecImpl<?>> choiceCases) {
562 this.choiceCases = choiceCases;
566 public Set<java.util.Map.Entry<CompositeNode, BindingCodec>> entrySet() {
571 public BindingCodec get(Object key) {
572 if (false == (key instanceof CompositeNode)) {
575 for (java.util.Map.Entry<Class, ChoiceCaseCodecImpl<?>> entry : choiceCases.entrySet()) {
576 ChoiceCaseCodecImpl<?> codec = entry.getValue();
577 if (codec.isAcceptable((CompositeNode) key)) {
578 return codec.getDelegate();
586 * This map is used as only facade for {@link BindingCodec} in different
587 * classloaders to retrieve codec dynamicly based on provided key.
592 @SuppressWarnings("rawtypes")
593 private static abstract class MapFacadeBase<T> implements Map<T, BindingCodec> {
596 public boolean containsKey(Object key) {
597 return get(key) != null;
601 public void clear() {
602 throw notModifiable();
606 public boolean equals(Object obj) {
607 return super.equals(obj);
611 public BindingCodec remove(Object key) {
621 public Collection<BindingCodec> values() {
625 private UnsupportedOperationException notModifiable() {
626 return new UnsupportedOperationException("Not externally modifiable.");
630 public BindingCodec<Map<QName, Object>, Object> put(T key, BindingCodec value) {
631 throw notModifiable();
635 public void putAll(Map<? extends T, ? extends BindingCodec> m) {
636 throw notModifiable();
640 public int hashCode() {
641 return super.hashCode();
645 public boolean isEmpty() {
650 public Set<T> keySet() {
655 public Set<java.util.Map.Entry<T, BindingCodec>> entrySet() {
660 public boolean containsValue(Object value) {
665 @SuppressWarnings({ "rawtypes", "unchecked" })
666 private class AugmentableCompositeCodec implements BindingCodec {
668 private final Class augmentableType;
670 Map<Class, BindingCodec> rawAugmentationCodecs = new WeakHashMap<>();
672 public AugmentableCompositeCodec(Class type) {
673 checkArgument(Augmentable.class.isAssignableFrom(type));
674 augmentableType = type;
678 public Object serialize(Object input) {
679 if (input instanceof Augmentable<?>) {
681 Map<Class, Augmentation> augmentations = getAugmentations(input);
682 return serializeImpl(augmentations);
687 private Map<Class, Augmentation> getAugmentations(Object input) {
688 Field augmentationField;
690 augmentationField = input.getClass().getDeclaredField("augmentation");
691 augmentationField.setAccessible(true);
692 Map<Class, Augmentation> augMap = (Map<Class, Augmentation>) augmentationField.get(input);
694 } catch (NoSuchFieldException e) {
696 } catch (SecurityException e) {
698 } catch (IllegalArgumentException e) {
700 } catch (IllegalAccessException e) {
703 return Collections.emptyMap();
706 private List serializeImpl(Map<Class, Augmentation> input) {
707 List ret = new ArrayList<>();
708 for (Entry<Class, Augmentation> entry : input.entrySet()) {
709 BindingCodec codec = getRawCodecForAugmentation(entry.getKey());
710 List output = (List) codec.serialize(new ValueWithQName(null, entry.getValue()));
716 private BindingCodec getRawCodecForAugmentation(Class key) {
717 BindingCodec ret = rawAugmentationCodecs.get(key);
722 Class<? extends BindingCodec> retClass = generator.augmentationTransformerFor(key);
723 ret = retClass.newInstance();
724 rawAugmentationCodecs.put(key, ret);
726 } catch (InstantiationException e) {
728 } catch (IllegalAccessException e) {
735 public Map<Class, Augmentation> deserialize(Object input) {
736 Map<Class, Augmentation> ret = new HashMap<>();
737 if (input instanceof CompositeNode) {
738 for (Entry<Class, BindingCodec> codec : rawAugmentationCodecs.entrySet()) {
739 Augmentation value = (Augmentation) codec.getValue().deserialize(input);
741 ret.put(codec.getKey(), value);
748 public Map<Class, BindingCodec> getRawAugmentationCodecs() {
749 return rawAugmentationCodecs;
752 public void setRawAugmentationCodecs(Map<Class, BindingCodec> rawAugmentationCodecs) {
753 this.rawAugmentationCodecs = rawAugmentationCodecs;
756 public Class getAugmentableType() {
757 return augmentableType;
761 @SuppressWarnings({ "rawtypes", "unchecked" })
762 private static class LateMixinCodec implements BindingCodec, Delegator<BindingCodec> {
764 private BindingCodec delegate;
767 public BindingCodec getDelegate() {
768 if (delegate == null) {
769 throw new IllegalStateException("Codec not initialized yet.");
775 public Object deserialize(Object input) {
776 return getDelegate().deserialize(input);
780 public Object serialize(Object input) {
781 return getDelegate().serialize(input);