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.DataObject;
40 import org.opendaylight.yangtools.yang.binding.Identifier;
41 import org.opendaylight.yangtools.yang.common.QName;
42 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
43 import org.opendaylight.yangtools.yang.data.api.Node;
44 import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
45 import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
46 import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
47 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
48 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
49 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
50 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
51 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
52 import org.slf4j.Logger;
53 import org.slf4j.LoggerFactory;
55 import static com.google.common.base.Preconditions.*;
56 import static org.opendaylight.controller.sal.binding.dom.serializer.impl.IntermediateMapping.*;
58 import org.opendaylight.yangtools.sal.binding.generator.impl.ModuleContext;
59 import org.opendaylight.yangtools.sal.binding.model.api.ConcreteType;
60 import org.opendaylight.yangtools.sal.binding.model.api.Type;
61 import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTypeBuilder;
62 import org.opendaylight.yangtools.yang.model.api.Module;
63 import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil;
65 public class LazyGeneratedCodecRegistry implements //
67 SchemaServiceListener, //
70 private final static Logger LOG = LoggerFactory.getLogger(LazyGeneratedCodecRegistry.class);
71 private final static LateMixinCodec NOT_READY_CODEC = new LateMixinCodec();
73 private final InstanceIdentifierCodec instanceIdentifierCodec = new InstanceIdentifierCodecImpl(this);
75 private TransformerGenerator generator;
77 // Concrete class to codecs
78 private Map<Class<?>, DataContainerCodec<?>> containerCodecs = new WeakHashMap<>();
79 private Map<Class<?>, IdentifierCodec<?>> identifierCodecs = new WeakHashMap<>();
80 private Map<Class<?>, ChoiceCodecImpl<?>> choiceCodecs = new WeakHashMap<>();
81 private Map<Class<?>, ChoiceCaseCodecImpl<?>> caseCodecs = new WeakHashMap<>();
82 private Map<Class<?>, AugmentableCompositeCodec> augmentableCodecs = new WeakHashMap<>();
84 /** Binding type to encountered classes mapping **/
85 @SuppressWarnings("rawtypes")
86 Map<Type, WeakReference<Class>> typeToClass = new ConcurrentHashMap<>();
88 @SuppressWarnings("rawtypes")
89 private ConcurrentMap<Type, ChoiceCaseCodecImpl> typeToCaseNodes = new ConcurrentHashMap<>();
91 private CaseClassMapFacade classToCaseRawCodec = new CaseClassMapFacade();
93 Map<SchemaPath, GeneratedTypeBuilder> pathToType = new ConcurrentHashMap<>();
95 private SchemaContext currentSchema;
97 public TransformerGenerator getGenerator() {
101 public void setGenerator(TransformerGenerator generator) {
102 this.generator = generator;
106 public InstanceIdentifierCodec getInstanceIdentifierCodec() {
107 return instanceIdentifierCodec;
111 public <T extends Augmentation<?>> AugmentationCodec<T> getCodecForAugmentation(Class<T> object) {
112 // TODO Auto-generated method stub
117 public Class<?> getClassForPath(List<QName> names) {
118 DataSchemaNode node = getSchemaNode(names);
119 SchemaPath path = node.getPath();
120 GeneratedTypeBuilder type = pathToType.get(path);
121 ReferencedTypeImpl typeref = new ReferencedTypeImpl(type.getPackageName(), type.getName());
122 @SuppressWarnings("rawtypes")
123 WeakReference<Class> weakRef = typeToClass.get(typeref);
124 if(weakRef == null) {
125 LOG.error("Could not find loaded class for path: {} and type: {}",path,typeref.getFullyQualifiedName());
127 return weakRef.get();
131 public IdentifierCodec<?> getKeyCodecForPath(List<QName> names) {
132 @SuppressWarnings("unchecked")
133 Class<? extends Identifiable<?>> cls = (Class<? extends Identifiable<?>>) getClassForPath(names);
134 return getIdentifierCodecForIdentifiable(cls);
138 public <T extends DataContainer> DataContainerCodec<T> getCodecForDataObject(Class<T> type) {
139 @SuppressWarnings("unchecked")
140 DataContainerCodec<T> ret = (DataContainerCodec<T>) containerCodecs.get(type);
144 Class<? extends BindingCodec<Map<QName, Object>, Object>> newType = generator.transformerFor(type);
145 BindingCodec<Map<QName, Object>, Object> rawCodec = newInstanceOf(newType);
146 DataContainerCodecImpl<T> newWrapper = new DataContainerCodecImpl<>(rawCodec);
147 containerCodecs.put(type, newWrapper);
152 @SuppressWarnings("rawtypes")
153 public void bindingClassEncountered(Class cls) {
155 ConcreteType typeRef = Types.typeForClass(cls);
156 if(typeToClass.containsKey(typeRef)) {
159 LOG.info("Binding Class {} encountered.",cls);
160 WeakReference<Class> weakRef = new WeakReference<>(cls);
161 typeToClass.put(typeRef, weakRef);
162 if(DataObject.class.isAssignableFrom(cls)) {
163 @SuppressWarnings({"unchecked","unused"})
164 Object cdc = getCodecForDataObject((Class<? extends DataObject>) cls);
169 public void onClassProcessed(Class<?> cls) {
170 ConcreteType typeRef = Types.typeForClass(cls);
171 if(typeToClass.containsKey(typeRef)) {
174 LOG.info("Binding Class {} encountered.",cls);
175 WeakReference<Class> weakRef = new WeakReference<>((Class) cls);
176 typeToClass.put(typeRef, weakRef);
179 private DataSchemaNode getSchemaNode(List<QName> path) {
180 QName firstNode = path.get(0);
181 DataNodeContainer previous = currentSchema.findModuleByNamespaceAndRevision(firstNode.getNamespace(),
182 firstNode.getRevision());
183 Iterator<QName> iterator = path.iterator();
184 while (iterator.hasNext()) {
185 QName arg = iterator.next();
186 DataSchemaNode currentNode = previous.getDataChildByName(arg);
187 if (currentNode == null && previous instanceof DataNodeContainer) {
188 currentNode = searchInChoices(previous, arg);
190 if (currentNode instanceof DataNodeContainer) {
191 previous = (DataNodeContainer) currentNode;
192 } else if (currentNode instanceof LeafSchemaNode || currentNode instanceof LeafListSchemaNode) {
193 checkState(!iterator.hasNext(), "Path tries to nest inside leaf node.");
197 return (DataSchemaNode) previous;
200 private DataSchemaNode searchInChoices(DataNodeContainer node, QName arg) {
201 Set<DataSchemaNode> children = node.getChildNodes();
202 for (DataSchemaNode child : children) {
203 if (child instanceof ChoiceNode) {
204 ChoiceNode choiceNode = (ChoiceNode) child;
205 DataSchemaNode potential = searchInCases(choiceNode, arg);
206 if (potential != null) {
214 private DataSchemaNode searchInCases(ChoiceNode choiceNode, QName arg) {
215 Set<ChoiceCaseNode> cases = choiceNode.getCases();
216 for (ChoiceCaseNode caseNode : cases) {
217 DataSchemaNode node = caseNode.getDataChildByName(arg);
225 private <T> T newInstanceOf(Class<?> newType) {
227 @SuppressWarnings("unchecked")
228 T ret = (T) newType.newInstance();
230 } catch (InstantiationException e) {
231 throw new IllegalStateException(e);
232 } catch (IllegalAccessException e) {
233 throw new IllegalStateException(e);
238 public <T extends Identifiable<?>> IdentifierCodec<?> getIdentifierCodecForIdentifiable(Class<T> type) {
239 IdentifierCodec<?> obj = identifierCodecs.get(type);
243 Class<? extends BindingCodec<Map<QName, Object>, Object>> newCodec = generator
244 .keyTransformerForIdentifiable(type);
245 BindingCodec<Map<QName, Object>, Object> newInstance;
246 newInstance = newInstanceOf(newCodec);
247 IdentifierCodecImpl<?> newWrapper = new IdentifierCodecImpl<>(newInstance);
248 identifierCodecs.put(type, newWrapper);
253 public void onCodecCreated(Class<?> cls) {
254 CodecMapping.setIdentifierCodec(cls, instanceIdentifierCodec);
258 public <T extends Identifier<?>> IdentifierCodec<T> getCodecForIdentifier(Class<T> object) {
259 @SuppressWarnings("unchecked")
260 IdentifierCodec<T> obj = (IdentifierCodec<T>) identifierCodecs.get(object);
264 Class<? extends BindingCodec<Map<QName, Object>, Object>> newCodec = generator
265 .keyTransformerForIdentifier(object);
266 BindingCodec<Map<QName, Object>, Object> newInstance;
267 newInstance = newInstanceOf(newCodec);
268 IdentifierCodecImpl<T> newWrapper = new IdentifierCodecImpl<>(newInstance);
269 identifierCodecs.put(object, newWrapper);
273 @SuppressWarnings("rawtypes")
274 public ChoiceCaseCodecImpl getCaseCodecFor(Class caseClass) {
275 ChoiceCaseCodecImpl<?> potential = caseCodecs.get(caseClass);
276 if (potential != null) {
279 ConcreteType typeref = Types.typeForClass(caseClass);
280 ChoiceCaseCodecImpl caseCodec = typeToCaseNodes.get(typeref);
282 @SuppressWarnings("unchecked")
283 Class<? extends BindingCodec> newCodec = generator.caseCodecFor(caseClass, caseCodec.schema);
284 BindingCodec newInstance = newInstanceOf(newCodec);
285 caseCodec.setDelegate(newInstance);
286 caseCodecs.put(caseClass, caseCodec);
288 for (Entry<Class<?>, ChoiceCodecImpl<?>> choice : choiceCodecs.entrySet()) {
289 if (choice.getKey().isAssignableFrom(caseClass)) {
290 choice.getValue().cases.put(caseClass, caseCodec);
296 public void onModuleContextAdded(SchemaContext schemaContext, Module module, ModuleContext context) {
297 pathToType.putAll(context.getChildNodes());
299 captureCases(context.getCases(), schemaContext);
302 private void captureCases(Map<SchemaPath, GeneratedTypeBuilder> cases, SchemaContext module) {
303 for (Entry<SchemaPath, GeneratedTypeBuilder> caseNode : cases.entrySet()) {
304 ReferencedTypeImpl typeref = new ReferencedTypeImpl(caseNode.getValue().getPackageName(), caseNode
305 .getValue().getName());
306 ChoiceCaseNode node = (ChoiceCaseNode) SchemaContextUtil.findDataSchemaNode(module, caseNode.getKey());
308 LOG.error("YANGTools Bug: SchemaNode for {}, with path {} was not found in context.",
309 typeref.getFullyQualifiedName(), caseNode.getKey());
313 @SuppressWarnings("rawtypes")
314 ChoiceCaseCodecImpl value = new ChoiceCaseCodecImpl(node);
315 typeToCaseNodes.putIfAbsent(typeref, value);
320 public void onGlobalContextUpdated(SchemaContext context) {
321 currentSchema = context;
324 @SuppressWarnings({ "unchecked", "rawtypes" })
326 public void onChoiceCodecCreated(Class<?> choiceClass,
327 Class<? extends BindingCodec<Map<QName, Object>, Object>> choiceCodec) {
328 ChoiceCodec<?> oldCodec = choiceCodecs.get(choiceClass);
329 checkState(oldCodec == null);
330 BindingCodec<Map<QName, Object>, Object> delegate = newInstanceOf(choiceCodec);
331 ChoiceCodecImpl<?> newCodec = new ChoiceCodecImpl(delegate);
332 choiceCodecs.put(choiceClass, newCodec);
333 CodecMapping.setClassToCaseMap(choiceCodec, (Map<Class<?>, BindingCodec<?, ?>>) classToCaseRawCodec);
334 CodecMapping.setCompositeNodeToCaseMap(choiceCodec, newCodec.getCompositeToCase());
339 public void onValueCodecCreated(Class<?> valueClass, Class<?> valueCodec) {
340 // TODO Auto-generated method stub
345 public void onCaseCodecCreated(Class<?> choiceClass,
346 Class<? extends BindingCodec<Map<QName, Object>, Object>> choiceCodec) {
347 // TODO Auto-generated method stub
352 public void onDataContainerCodecCreated(Class<?> dataClass,
353 Class<? extends BindingCodec<Map<QName, Object>, Object>> dataCodec) {
354 if (Augmentable.class.isAssignableFrom(dataClass)) {
355 AugmentableCompositeCodec augmentableCodec = getAugmentableCodec(dataClass);
356 CodecMapping.setAugmentationCodec(dataCodec, augmentableCodec);
361 private AugmentableCompositeCodec getAugmentableCodec(Class<?> dataClass) {
362 AugmentableCompositeCodec ret = augmentableCodecs.get(dataClass);
366 ret = new AugmentableCompositeCodec(dataClass);
367 augmentableCodecs.put(dataClass, ret);
371 private static abstract class IntermediateCodec<T> implements //
372 DomCodec<T>, Delegator<BindingCodec<Map<QName, Object>, Object>> {
374 private final BindingCodec<Map<QName, Object>, Object> delegate;
377 public BindingCodec<Map<QName, Object>, Object> getDelegate() {
381 public IntermediateCodec(BindingCodec<Map<QName, Object>, Object> delegate) {
382 this.delegate = delegate;
386 public Node<?> serialize(ValueWithQName<T> input) {
387 Map<QName, Object> intermediateOutput = delegate.serialize(input);
388 return toNode(intermediateOutput);
392 private static class IdentifierCodecImpl<T extends Identifier<?>> //
393 extends IntermediateCodec<T> //
394 implements IdentifierCodec<T> {
396 public IdentifierCodecImpl(BindingCodec<Map<QName, Object>, Object> delegate) {
401 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 private static class DataContainerCodecImpl<T extends DataContainer> //
415 extends IntermediateCodec<T> //
416 implements DataContainerCodec<T> {
418 public DataContainerCodecImpl(BindingCodec<Map<QName, Object>, Object> delegate) {
423 public ValueWithQName<T> deserialize(Node<?> input) {
427 QName qname = input.getNodeType();
428 @SuppressWarnings("unchecked")
429 T value = (T) getDelegate().deserialize((Map<QName, Object>) input);
430 return new ValueWithQName<T>(qname, value);
434 public CompositeNode serialize(ValueWithQName<T> input) {
435 return (CompositeNode) super.serialize(input);
439 @SuppressWarnings("rawtypes")
440 private static class ChoiceCaseCodecImpl<T extends DataContainer> implements ChoiceCaseCodec<T>, //
441 Delegator<BindingCodec> {
442 private final boolean augmenting;
443 private BindingCodec delegate;
445 private final Set<String> validNames;
446 private final Set<QName> validQNames;
447 private ChoiceCaseNode schema;
449 public ChoiceCaseCodecImpl(ChoiceCaseNode caseNode) {
450 this.delegate = NOT_READY_CODEC;
451 this.schema = caseNode;
452 validNames = new HashSet<>();
453 validQNames = new HashSet<>();
454 for (DataSchemaNode node : caseNode.getChildNodes()) {
455 QName qname = node.getQName();
456 validQNames.add(qname);
457 validNames.add(qname.getLocalName());
459 augmenting = caseNode.isAugmenting();
463 public ValueWithQName<T> deserialize(Node<?> input) {
464 throw new UnsupportedOperationException("Direct invocation of this codec is not allowed.");
468 public CompositeNode serialize(ValueWithQName<T> input) {
469 throw new UnsupportedOperationException("Direct invocation of this codec is not allowed.");
472 public BindingCodec getDelegate() {
476 public void setDelegate(BindingCodec delegate) {
477 this.delegate = delegate;
480 public ChoiceCaseNode getSchema() {
485 public boolean isAcceptable(Node<?> input) {
486 if (false == (input instanceof CompositeNode)) {
488 return checkAugmenting((CompositeNode) input);
490 return checkLocal((CompositeNode) input);
496 private boolean checkLocal(CompositeNode input) {
497 QName parent = input.getNodeType();
498 for (Node<?> childNode : input.getChildren()) {
499 QName child = childNode.getNodeType();
500 if (false == Objects.equals(parent.getNamespace(), child.getNamespace())) {
503 if (false == Objects.equals(parent.getRevision(), child.getRevision())) {
506 if (validNames.contains(child.getLocalName())) {
513 private boolean checkAugmenting(CompositeNode input) {
514 for (Node<?> child : input.getChildren()) {
515 if (validQNames.contains(child.getNodeType())) {
523 private static class ChoiceCodecImpl<T> implements ChoiceCodec<T> {
525 private final BindingCodec<Map<QName, Object>, Object> delegate;
527 @SuppressWarnings("rawtypes")
528 private final Map<Class, ChoiceCaseCodecImpl<?>> cases = new WeakHashMap<>();
530 private final CaseCompositeNodeMapFacade CompositeToCase;
532 public ChoiceCodecImpl(BindingCodec<Map<QName, Object>, Object> delegate) {
533 this.delegate = delegate;
534 this.CompositeToCase = new CaseCompositeNodeMapFacade(cases);
538 public ValueWithQName<T> deserialize(Node<?> input) {
539 throw new UnsupportedOperationException("Direct invocation of this codec is not allowed.");
543 public Node<?> serialize(ValueWithQName<T> input) {
544 throw new UnsupportedOperationException("Direct invocation of this codec is not allowed.");
547 public CaseCompositeNodeMapFacade getCompositeToCase() {
548 return CompositeToCase;
551 public Map<Class, ChoiceCaseCodecImpl<?>> getCases() {
555 public BindingCodec<Map<QName, Object>, Object> getDelegate() {
561 @SuppressWarnings("rawtypes")
562 private class CaseClassMapFacade extends MapFacadeBase {
565 public Set<java.util.Map.Entry<Class, BindingCodec<Object, Object>>> entrySet() {
570 public BindingCodec get(Object key) {
571 if (key instanceof Class) {
572 Class cls = (Class) key;
573 //bindingClassEncountered(cls);
574 ChoiceCaseCodecImpl caseCodec = getCaseCodecFor(cls);
575 return caseCodec.getDelegate();
581 @SuppressWarnings("rawtypes")
582 private static class CaseCompositeNodeMapFacade extends MapFacadeBase<CompositeNode> {
584 final Map<Class, ChoiceCaseCodecImpl<?>> choiceCases;
586 public CaseCompositeNodeMapFacade(Map<Class, ChoiceCaseCodecImpl<?>> choiceCases) {
587 this.choiceCases = choiceCases;
591 public BindingCodec get(Object key) {
592 if (false == (key instanceof CompositeNode)) {
595 for (java.util.Map.Entry<Class, ChoiceCaseCodecImpl<?>> entry : choiceCases.entrySet()) {
596 ChoiceCaseCodecImpl<?> codec = entry.getValue();
597 if (codec.isAcceptable((CompositeNode) key)) {
598 return codec.getDelegate();
608 * This map is used as only facade for {@link BindingCodec} in different
609 * classloaders to retrieve codec dynamicly based on provided key.
614 @SuppressWarnings("rawtypes")
615 private static abstract class MapFacadeBase<T> implements Map<T, BindingCodec<?, ?>> {
618 public boolean containsKey(Object key) {
619 return get(key) != null;
623 public void clear() {
624 throw notModifiable();
628 public boolean equals(Object obj) {
629 return super.equals(obj);
633 public BindingCodec remove(Object key) {
643 public Collection<BindingCodec<?, ?>> values() {
647 private UnsupportedOperationException notModifiable() {
648 return new UnsupportedOperationException("Not externally modifiable.");
652 public BindingCodec<Map<QName, Object>, Object> put(T key, BindingCodec<?,?> value) {
653 throw notModifiable();
657 public void putAll(Map<? extends T, ? extends BindingCodec<?, ?>> m) {
658 throw notModifiable();
662 public int hashCode() {
663 return super.hashCode();
667 public boolean isEmpty() {
672 public Set<T> keySet() {
677 public Set<java.util.Map.Entry<T, BindingCodec<?, ?>>> entrySet() {
678 // TODO Auto-generated method stub
683 public boolean containsValue(Object value) {
688 @SuppressWarnings({ "rawtypes", "unchecked" })
689 private class AugmentableCompositeCodec implements BindingCodec {
691 private final Class augmentableType;
693 Map<Class, BindingCodec> rawAugmentationCodecs = new WeakHashMap<>();
695 public AugmentableCompositeCodec(Class type) {
696 checkArgument(Augmentable.class.isAssignableFrom(type));
697 augmentableType = type;
701 public Object serialize(Object input) {
702 if (input instanceof Augmentable<?>) {
704 Map<Class, Augmentation> augmentations = getAugmentations(input);
705 return serializeImpl(augmentations);
710 private Map<Class, Augmentation> getAugmentations(Object input) {
711 Field augmentationField;
713 augmentationField = input.getClass().getDeclaredField("augmentation");
714 augmentationField.setAccessible(true);
715 Map<Class, Augmentation> augMap = (Map<Class, Augmentation>) augmentationField.get(input);
717 } catch (NoSuchFieldException e) {
719 } catch (SecurityException e) {
721 } catch (IllegalArgumentException e) {
723 } catch (IllegalAccessException e) {
726 return Collections.emptyMap();
729 private List serializeImpl(Map<Class, Augmentation> input) {
730 List ret = new ArrayList<>();
731 for (Entry<Class, Augmentation> entry : input.entrySet()) {
732 BindingCodec codec = getRawCodecForAugmentation(entry.getKey());
733 List output = (List) codec.serialize(new ValueWithQName(null, entry.getValue()));
739 private BindingCodec getRawCodecForAugmentation(Class key) {
740 BindingCodec ret = rawAugmentationCodecs.get(key);
745 Class<? extends BindingCodec> retClass = generator.augmentationTransformerFor(key);
746 ret = retClass.newInstance();
747 rawAugmentationCodecs.put(key, ret);
749 } catch (InstantiationException e) {
751 } catch (IllegalAccessException e) {
758 public Map<Class, Augmentation> deserialize(Object input) {
759 Map<Class, Augmentation> ret = new HashMap<>();
760 if (input instanceof CompositeNode) {
761 for (Entry<Class, BindingCodec> codec : rawAugmentationCodecs.entrySet()) {
762 Augmentation value = (Augmentation) codec.getValue().deserialize(input);
764 ret.put(codec.getKey(), value);
771 public Map<Class, BindingCodec> getRawAugmentationCodecs() {
772 return rawAugmentationCodecs;
775 public void setRawAugmentationCodecs(Map<Class, BindingCodec> rawAugmentationCodecs) {
776 this.rawAugmentationCodecs = rawAugmentationCodecs;
779 public Class getAugmentableType() {
780 return augmentableType;
784 @SuppressWarnings({ "rawtypes", "unchecked" })
785 private static class LateMixinCodec implements BindingCodec, Delegator<BindingCodec> {
787 private BindingCodec delegate;
790 public BindingCodec getDelegate() {
791 if (delegate == null) {
792 throw new IllegalStateException("Codec not initialized yet.");
798 public Object deserialize(Object input) {
799 return getDelegate().deserialize(input);
803 public Object serialize(Object input) {
804 return getDelegate().serialize(input);