X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=blobdiff_plain;f=opendaylight%2Fmd-sal%2Fsal-rest-connector%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fsal%2Frestconf%2Fimpl%2FRestCodec.java;h=14b8282312d7accd1ba0c912a55178c72d3f317c;hp=40fba88356e89f924e6c2903e7460102a74d818c;hb=92f1fd15e99ce5b9e52612c0b52f70cd661b99cc;hpb=79eba117e59f10c8bff34d0dd6bbb67b8ccc3e10 diff --git a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestCodec.java b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestCodec.java index 40fba88356..14b8282312 100644 --- a/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestCodec.java +++ b/opendaylight/md-sal/sal-rest-connector/src/main/java/org/opendaylight/controller/sal/restconf/impl/RestCodec.java @@ -1,27 +1,54 @@ +/* + * 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.controller.sal.restconf.impl; import java.net.URI; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.opendaylight.controller.sal.core.api.mount.MountInstance; import org.opendaylight.controller.sal.rest.impl.RestUtil; import org.opendaylight.controller.sal.restconf.impl.IdentityValuesDTO.IdentityValue; +import org.opendaylight.controller.sal.restconf.impl.IdentityValuesDTO.Predicate; import org.opendaylight.yangtools.concepts.Codec; import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier; +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.NodeWithValue; +import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument; import org.opendaylight.yangtools.yang.data.api.codec.IdentityrefCodec; +import org.opendaylight.yangtools.yang.data.api.codec.InstanceIdentifierCodec; import org.opendaylight.yangtools.yang.data.api.codec.LeafrefCodec; import org.opendaylight.yangtools.yang.data.impl.codec.TypeDefinitionAwareCodec; +import org.opendaylight.yangtools.yang.model.api.DataNodeContainer; +import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; +import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode; +import org.opendaylight.yangtools.yang.model.api.ListSchemaNode; +import org.opendaylight.yangtools.yang.model.api.Module; import org.opendaylight.yangtools.yang.model.api.TypeDefinition; import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition; +import org.opendaylight.yangtools.yang.model.api.type.InstanceIdentifierTypeDefinition; import org.opendaylight.yangtools.yang.model.api.type.LeafrefTypeDefinition; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class RestCodec { + private static final Logger logger = LoggerFactory.getLogger(RestCodec.class); + private RestCodec() { } - public static final Codec from(TypeDefinition typeDefinition) { - return new ObjectCodec(typeDefinition); + public static final Codec from(final TypeDefinition typeDefinition, final MountInstance mountPoint) { + return new ObjectCodec(typeDefinition, mountPoint); } @SuppressWarnings("rawtypes") @@ -29,27 +56,58 @@ public class RestCodec { private final Logger logger = LoggerFactory.getLogger(RestCodec.class); - public static final Codec IDENTITYREF_DEFAULT_CODEC = new IdentityrefCodecImpl(); public static final Codec LEAFREF_DEFAULT_CODEC = new LeafrefCodecImpl(); + private final Codec instanceIdentifier; + private final Codec identityrefCodec; - private TypeDefinition type; + private final TypeDefinition type; - private ObjectCodec(TypeDefinition typeDefinition) { + private ObjectCodec(final TypeDefinition typeDefinition, final MountInstance mountPoint) { type = RestUtil.resolveBaseTypeFrom(typeDefinition); + if (type instanceof IdentityrefTypeDefinition) { + identityrefCodec = new IdentityrefCodecImpl(mountPoint); + } else { + identityrefCodec = null; + } + if (type instanceof InstanceIdentifierTypeDefinition) { + instanceIdentifier = new InstanceIdentifierCodecImpl(mountPoint); + } else { + instanceIdentifier = null; + } } @SuppressWarnings("unchecked") @Override - public Object deserialize(Object input) { + public Object deserialize(final Object input) { try { if (type instanceof IdentityrefTypeDefinition) { - return IDENTITYREF_DEFAULT_CODEC.deserialize(input); + if (input instanceof IdentityValuesDTO) { + return identityrefCodec.deserialize(input); + } + logger.info( + "Value is not instance of IdentityrefTypeDefinition but is {}. Therefore NULL is used as translation of - {}", + input == null ? "null" : input.getClass(), String.valueOf(input)); + return null; } else if (type instanceof LeafrefTypeDefinition) { + if (input instanceof IdentityValuesDTO) { + return LEAFREF_DEFAULT_CODEC.deserialize(((IdentityValuesDTO)input).getOriginValue()); + } return LEAFREF_DEFAULT_CODEC.deserialize(input); + } else if (type instanceof InstanceIdentifierTypeDefinition) { + if (input instanceof IdentityValuesDTO) { + return instanceIdentifier.deserialize(input); + } + logger.info( + "Value is not instance of InstanceIdentifierTypeDefinition but is {}. Therefore NULL is used as translation of - {}", + input == null ? "null" : input.getClass(), String.valueOf(input)); + return null; } else { TypeDefinitionAwareCodec> typeAwarecodec = TypeDefinitionAwareCodec .from(type); if (typeAwarecodec != null) { + if (input instanceof IdentityValuesDTO) { + return typeAwarecodec.deserialize(((IdentityValuesDTO)input).getOriginValue()); + } return typeAwarecodec.deserialize(String.valueOf(input)); } else { logger.debug("Codec for type \"" + type.getQName().getLocalName() @@ -58,22 +116,24 @@ public class RestCodec { } } } catch (ClassCastException e) { // TODO remove this catch when - // everyone use codecs + // everyone use codecs logger.error( "ClassCastException was thrown when codec is invoked with parameter " + String.valueOf(input), e); - return input; + return null; } } @SuppressWarnings("unchecked") @Override - public Object serialize(Object input) { + public Object serialize(final Object input) { try { if (type instanceof IdentityrefTypeDefinition) { - return IDENTITYREF_DEFAULT_CODEC.serialize(input); + return identityrefCodec.serialize(input); } else if (type instanceof LeafrefTypeDefinition) { return LEAFREF_DEFAULT_CODEC.serialize(input); + } else if (type instanceof InstanceIdentifierTypeDefinition) { + return instanceIdentifier.serialize(input); } else { TypeDefinitionAwareCodec> typeAwarecodec = TypeDefinitionAwareCodec .from(type); @@ -86,7 +146,7 @@ public class RestCodec { } } } catch (ClassCastException e) { // TODO remove this catch when - // everyone use codecs + // everyone use codecs logger.error( "ClassCastException was thrown when codec is invoked with parameter " + String.valueOf(input), e); @@ -98,20 +158,30 @@ public class RestCodec { public static class IdentityrefCodecImpl implements IdentityrefCodec { + private final Logger logger = LoggerFactory.getLogger(IdentityrefCodecImpl.class); + + private final MountInstance mountPoint; + + public IdentityrefCodecImpl(final MountInstance mountPoint) { + this.mountPoint = mountPoint; + } + @Override - public IdentityValuesDTO serialize(QName data) { - return new IdentityValuesDTO(data.getNamespace().toString(), data.getLocalName(), data.getPrefix()); + public IdentityValuesDTO serialize(final QName data) { + return new IdentityValuesDTO(data.getNamespace().toString(), data.getLocalName(), data.getPrefix(),null); } @Override - public QName deserialize(IdentityValuesDTO data) { + public QName deserialize(final IdentityValuesDTO data) { IdentityValue valueWithNamespace = data.getValuesWithNamespaces().get(0); - String namespace = valueWithNamespace.getNamespace(); - URI validNamespace = ControllerContext.getInstance().findNamespaceByModule(namespace); - if (validNamespace == null) { - validNamespace = URI.create(namespace); + Module module = getModuleByNamespace(valueWithNamespace.getNamespace(), mountPoint); + if (module == null) { + logger.info("Module was not found for namespace {}", valueWithNamespace.getNamespace()); + logger.info("Idenetityref will be translated as NULL for data - {}", String.valueOf(valueWithNamespace)); + return null; } - return QName.create(validNamespace, null, valueWithNamespace.getValue()); + + return QName.create(module.getNamespace(), module.getRevision(), valueWithNamespace.getValue()); } } @@ -119,15 +189,157 @@ public class RestCodec { public static class LeafrefCodecImpl implements LeafrefCodec { @Override - public String serialize(Object data) { + public String serialize(final Object data) { return String.valueOf(data); } @Override - public Object deserialize(String data) { + public Object deserialize(final String data) { return data; } } + public static class InstanceIdentifierCodecImpl implements InstanceIdentifierCodec { + private final Logger logger = LoggerFactory.getLogger(InstanceIdentifierCodecImpl.class); + private final MountInstance mountPoint; + + public InstanceIdentifierCodecImpl(final MountInstance mountPoint) { + this.mountPoint = mountPoint; + } + + @Override + public IdentityValuesDTO serialize(final InstanceIdentifier data) { + IdentityValuesDTO identityValuesDTO = new IdentityValuesDTO(); + for (PathArgument pathArgument : data.getPathArguments()) { + IdentityValue identityValue = qNameToIdentityValue(pathArgument.getNodeType()); + if (pathArgument instanceof NodeIdentifierWithPredicates && identityValue != null) { + List predicates = keyValuesToPredicateList(((NodeIdentifierWithPredicates) pathArgument) + .getKeyValues()); + identityValue.setPredicates(predicates); + } else if (pathArgument instanceof NodeWithValue && identityValue != null) { + List predicates = new ArrayList<>(); + String value = String.valueOf(((NodeWithValue) pathArgument).getValue()); + predicates.add(new Predicate(null, value)); + identityValue.setPredicates(predicates); + } + identityValuesDTO.add(identityValue); + } + return identityValuesDTO; + } + + @Override + public InstanceIdentifier deserialize(final IdentityValuesDTO data) { + List result = new ArrayList(); + IdentityValue valueWithNamespace = data.getValuesWithNamespaces().get(0); + Module module = getModuleByNamespace(valueWithNamespace.getNamespace(), mountPoint); + if (module == null) { + logger.info("Module by namespace '{}' of first node in instance-identiefier was not found.", valueWithNamespace.getNamespace()); + logger.info("Instance-identifier will be translated as NULL for data - {}", String.valueOf(valueWithNamespace.getValue())); + return null; + } + + DataNodeContainer parentContainer = module; + List identities = data.getValuesWithNamespaces(); + for (int i = 0; i < identities.size(); i++) { + IdentityValue identityValue = identities.get(i); + URI validNamespace = resolveValidNamespace(identityValue.getNamespace(), mountPoint); + DataSchemaNode node = ControllerContext.getInstance().findInstanceDataChildByNameAndNamespace( + parentContainer, identityValue.getValue(), validNamespace); + if (node == null) { + logger.info("'{}' node was not found in {}", identityValue, parentContainer.getChildNodes()); + logger.info("Instance-identifier will be translated as NULL for data - {}", String.valueOf(identityValue.getValue())); + return null; + } + QName qName = node.getQName(); + PathArgument pathArgument = null; + if (identityValue.getPredicates().isEmpty()) { + pathArgument = new NodeIdentifier(qName); + } else { + if (node instanceof LeafListSchemaNode) { // predicate is value of leaf-list entry + Predicate leafListPredicate = identityValue.getPredicates().get(0); + if (!leafListPredicate.isLeafList()) { + logger.info("Predicate's data is not type of leaf-list. It should be in format \".='value'\""); + logger.info("Instance-identifier will be translated as NULL for data - {}", String.valueOf(identityValue.getValue())); + return null; + } + pathArgument = new NodeWithValue(qName, leafListPredicate.getValue()); + } else if (node instanceof ListSchemaNode) { // predicates are keys of list + DataNodeContainer listNode = (DataNodeContainer) node; + Map predicatesMap = new HashMap<>(); + for (Predicate predicate : identityValue.getPredicates()) { + validNamespace = resolveValidNamespace(predicate.getName().getNamespace(), mountPoint); + DataSchemaNode listKey = ControllerContext.getInstance().findInstanceDataChildByNameAndNamespace( + listNode, predicate.getName().getValue(), validNamespace); + predicatesMap.put(listKey.getQName(), predicate.getValue()); + } + pathArgument = new NodeIdentifierWithPredicates(qName, predicatesMap); + } else { + logger.info("Node {} is not List or Leaf-list.", node); + logger.info("Instance-identifier will be translated as NULL for data - {}", String.valueOf(identityValue.getValue())); + return null; + } + } + result.add(pathArgument); + if (i < identities.size() - 1) { // last element in instance-identifier can be other than DataNodeContainer + if (node instanceof DataNodeContainer) { + parentContainer = (DataNodeContainer) node; + } else { + logger.info("Node {} isn't instance of DataNodeContainer", node); + logger.info("Instance-identifier will be translated as NULL for data - {}", String.valueOf(identityValue.getValue())); + return null; + } + } + } + + return result.isEmpty() ? null : InstanceIdentifier.create(result); + } + + private List keyValuesToPredicateList(final Map keyValues) { + List result = new ArrayList<>(); + for (QName qName : keyValues.keySet()) { + Object value = keyValues.get(qName); + result.add(new Predicate(qNameToIdentityValue(qName), String.valueOf(value))); + } + return result; + } + + private IdentityValue qNameToIdentityValue(final QName qName) { + if (qName != null) { + return new IdentityValue(qName.getNamespace().toString(), qName.getLocalName(), qName.getPrefix()); + } + return null; + } + } + + private static Module getModuleByNamespace(final String namespace, final MountInstance mountPoint) { + URI validNamespace = resolveValidNamespace(namespace, mountPoint); + + Module module = null; + if (mountPoint != null) { + module = ControllerContext.getInstance().findModuleByNamespace(mountPoint, validNamespace); + } else { + module = ControllerContext.getInstance().findModuleByNamespace(validNamespace); + } + if (module == null) { + logger.info("Module for namespace " + validNamespace + " wasn't found."); + return null; + } + return module; + } + + private static URI resolveValidNamespace(final String namespace, final MountInstance mountPoint) { + URI validNamespace; + if (mountPoint != null) { + validNamespace = ControllerContext.getInstance().findNamespaceByModuleName(mountPoint, namespace); + } else { + validNamespace = ControllerContext.getInstance().findNamespaceByModuleName(namespace); + } + if (validNamespace == null) { + validNamespace = URI.create(namespace); + } + + return validNamespace; + } + }