/** * Copyright (c) 2014 Cisco Systems, Inc. and others. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html */ package org.opendaylight.yangtools.sal.binding.generator.impl; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import java.util.WeakHashMap; import java.util.concurrent.ConcurrentHashMap; import org.opendaylight.yangtools.concepts.Identifiable; import org.opendaylight.yangtools.yang.binding.Augmentation; import org.opendaylight.yangtools.yang.binding.DataObject; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem; import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.Item; import org.opendaylight.yangtools.yang.binding.util.BindingReflections; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.data.api.CompositeNode; import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier; import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates; import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument; import org.opendaylight.yangtools.yang.data.api.Node; import org.opendaylight.yangtools.yang.data.impl.CompositeNodeTOImpl; import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl; import org.opendaylight.yangtools.yang.data.impl.codec.CodecRegistry; import org.opendaylight.yangtools.yang.data.impl.codec.IdentifierCodec; import org.opendaylight.yangtools.yang.data.impl.codec.InstanceIdentifierCodec; import org.opendaylight.yangtools.yang.data.impl.codec.ValueWithQName; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.google.common.collect.ImmutableList; public class InstanceIdentifierCodecImpl implements InstanceIdentifierCodec { private static final Logger LOG = LoggerFactory.getLogger(InstanceIdentifierCodecImpl.class); private final CodecRegistry codecRegistry; private final Map, Map, Class>> classToPreviousAugment = Collections .synchronizedMap(new WeakHashMap, Map, Class>>()); public InstanceIdentifierCodecImpl(final CodecRegistry registry) { this.codecRegistry = registry; } @Override public InstanceIdentifier deserialize( final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier input) { Class baType = null; List biArgs = input.getPath(); List scannedPath = new ArrayList<>(biArgs.size()); List baArgs = new ArrayList(biArgs.size()); for (org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument biArg : biArgs) { scannedPath.add(biArg.getNodeType()); org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument baArg = deserializePathArgument( biArg, scannedPath); if (baArg != null) { baType = baArg.getType(); } Map, Class> injectAugment = classToPreviousAugment.get(baType); if (injectAugment != null) { Class augment = (Class) injectAugment.get(scannedPath); if (augment != null) { baArgs.add(new Item(augment)); } } baArgs.add(baArg); } InstanceIdentifier ret = InstanceIdentifier.create(baArgs); LOG.debug("DOM Instance Identifier {} deserialized to {}", input, ret); return ret; } @Override public InstanceIdentifier deserialize( final org.opendaylight.yangtools.yang.data.api.InstanceIdentifier input, InstanceIdentifier bindingIdentifier) { return deserialize(input); } private org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument _deserializePathArgument( final NodeIdentifier argument, final List processedPath) { final Class cls = codecRegistry.getClassForPath(processedPath); Item item = new Item<>(cls); return item; } private org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument _deserializePathArgument( final NodeIdentifierWithPredicates argument, final List processedPath) { final Class type = codecRegistry.getClassForPath(processedPath); final IdentifierCodec codec = codecRegistry .> getIdentifierCodecForIdentifiable(type); CompositeNode _compositeNode = this.toCompositeNode(argument); ValueWithQName deserialize = codec.deserialize(_compositeNode); Object value = null; if (deserialize != null) { value = deserialize.getValue(); } return CodecTypeUtils.newIdentifiableItem(type, value); } public CompositeNode toCompositeNode(final NodeIdentifierWithPredicates predicates) { Set> keyValues = predicates.getKeyValues().entrySet(); List> values = new ArrayList<>(keyValues.size()); for (Map.Entry keyValue : keyValues) { values.add(new SimpleNodeTOImpl(keyValue.getKey(), null, keyValue.getValue())); } return new CompositeNodeTOImpl(predicates.getNodeType(), null, values); } @Override public org.opendaylight.yangtools.yang.data.api.InstanceIdentifier serialize(final InstanceIdentifier input) { Class previousAugmentation = null; List pathArgs = input.getPath(); QName previousQName = null; List components = new ArrayList<>(pathArgs.size()); List qnamePath = new ArrayList<>(pathArgs.size()); for (InstanceIdentifier.PathArgument baArg : pathArgs) { if (!Augmentation.class.isAssignableFrom(baArg.getType())) { org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument biArg = serializePathArgument( baArg, previousQName); previousQName = biArg.getNodeType(); components.add(biArg); qnamePath.add(biArg.getNodeType()); ImmutableList immutableList = ImmutableList.copyOf(qnamePath); codecRegistry.putPathToClass(immutableList, baArg.getType()); if (previousAugmentation != null) { updateAugmentationInjection(baArg.getType(), immutableList, previousAugmentation); } previousAugmentation = null; } else { previousQName = codecRegistry.getQNameForAugmentation(baArg.getType()); previousAugmentation = baArg.getType(); } } org.opendaylight.yangtools.yang.data.api.InstanceIdentifier ret = new org.opendaylight.yangtools.yang.data.api.InstanceIdentifier( components); LOG.debug("Binding Instance Identifier {} serialized to DOM InstanceIdentifier {}", input, ret); return ret; } public Class updateAugmentationInjection(final Class class1, final ImmutableList list, final Class augmentation) { if (classToPreviousAugment.get(class1) == null) { classToPreviousAugment.put(class1, new ConcurrentHashMap, Class>()); } return classToPreviousAugment.get(class1).put(list, augmentation); } private PathArgument _serializePathArgument(final Item argument, final QName previousQname) { Class type = argument.getType(); QName qname = BindingReflections.findQName(type); if (previousQname == null || (BindingReflections.isAugmentationChild(argument.getType()))) { return new NodeIdentifier(qname); } return new NodeIdentifier(QName.create(previousQname, qname.getLocalName())); } private PathArgument _serializePathArgument(final IdentifiableItem argument, final QName previousQname) { Map predicates = new HashMap<>(); Class type = argument.getType(); IdentifierCodec keyCodec = codecRegistry.getIdentifierCodecForIdentifiable(type); QName qname = BindingReflections.findQName(type); if (previousQname != null && !(BindingReflections.isAugmentationChild(argument.getType()))) { qname = QName.create(previousQname, qname.getLocalName()); } ValueWithQName combinedInput = new ValueWithQName(previousQname, argument.getKey()); CompositeNode compositeOutput = keyCodec.serialize(combinedInput); for (Node outputValue : compositeOutput.getValue()) { predicates.put(outputValue.getNodeType(), outputValue.getValue()); } if (previousQname == null) { return new NodeIdentifierWithPredicates(qname, predicates); } return new NodeIdentifierWithPredicates(qname, predicates); } private org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument deserializePathArgument( final PathArgument argument, final List processedPath) { if (argument instanceof NodeIdentifier) { return _deserializePathArgument((NodeIdentifier) argument, processedPath); } else if (argument instanceof NodeIdentifierWithPredicates) { return _deserializePathArgument((NodeIdentifierWithPredicates) argument, processedPath); } else { throw new IllegalArgumentException("Unhandled parameter types: " + Arrays. asList(argument, processedPath).toString()); } } private PathArgument serializePathArgument( final org.opendaylight.yangtools.yang.binding.InstanceIdentifier.PathArgument argument, final QName previousQname) { if (argument instanceof IdentifiableItem) { return _serializePathArgument((IdentifiableItem) argument, previousQname); } else if (argument instanceof Item) { return _serializePathArgument((Item) argument, previousQname); } else { throw new IllegalArgumentException("Unhandled parameter types: " + Arrays. asList(argument, previousQname).toString()); } } }