}
typeDefinitionsConcreteDepth.add(unsortedTypeDefinition);
}
- // keys are in ascending order
- for (Map.Entry<Integer, List<TypeDefinition<?>>> entry : typeDefinitionsDepths.entrySet()) {
- sortedTypeDefinition.addAll(entry.getValue());
+
+ // SortedMap guarantees order corresponding to keys in ascending order
+ for (List<TypeDefinition<?>> v : typeDefinitionsDepths.values()) {
+ sortedTypeDefinition.addAll(v);
}
return sortedTypeDefinition;
<repository>
<id>opendaylight-mirror</id>
<name>opendaylight-mirror</name>
- <url>http://nexus.opendaylight.org/content/groups/public/</url>
+ <url>${nexusproxy}/groups/public/</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
<repository>
<id>opendaylight-snapshot</id>
<name>opendaylight-snapshot</name>
- <url>http://nexus.opendaylight.org/content/repositories/opendaylight.snapshot/</url>
+ <url>${nexusproxy}/repositories/opendaylight.snapshot/</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>yang-data-impl</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-data-util</artifactId>
+ </dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
<artifactId>yang-parser-impl</artifactId>
--- /dev/null
+/*
+ * 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.yang.data.codec.gson;
+
+import com.google.common.annotations.Beta;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
+
+import org.opendaylight.yangtools.concepts.Codec;
+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.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.LeafrefTypeDefinition;
+import org.opendaylight.yangtools.yang.model.util.IdentityrefType;
+import org.opendaylight.yangtools.yang.model.util.InstanceIdentifierType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This class is implementation-internal and subject to change. Please do not use it.
+ */
+@Beta
+final class CodecFactory {
+ private static final Logger LOG = LoggerFactory.getLogger(CodecFactory.class);
+ private static final Codec<?, ?> LEAFREF_DEFAULT_CODEC = new LeafrefCodec<String>() {
+ @Override
+ public String serialize(final Object data) {
+ return String.valueOf(data);
+ }
+
+ @Override
+ public Object deserialize(final String data) {
+ return data;
+ }
+ };
+ private static final Codec<?, ?> NULL_CODEC = new Codec<Object, Object>() {
+ @Override
+ public Object deserialize(final Object input) {
+ return null;
+ }
+
+ @Override
+ public Object serialize(final Object input) {
+ return null;
+ }
+ };
+
+
+ private static TypeDefinition<?> resolveBaseTypeFrom(final TypeDefinition<?> type) {
+ TypeDefinition<?> superType = type;
+ while (superType.getBaseType() != null) {
+ superType = superType.getBaseType();
+ }
+ return superType;
+ }
+
+ private final LoadingCache<TypeDefinition<?>, Codec<?, ?>> codecs =
+ CacheBuilder.newBuilder().softValues().build(new CacheLoader<TypeDefinition<?>, Codec<?, ?>>() {
+ @Override
+ public Codec<?, ?> load(final TypeDefinition<?> key) throws Exception {
+ final TypeDefinition<?> type = resolveBaseTypeFrom(key);
+
+ if (type instanceof InstanceIdentifierType) {
+ return iidCodec;
+ }
+ if (type instanceof IdentityrefType) {
+ return idrefCodec;
+ }
+ if (type instanceof LeafrefTypeDefinition) {
+ return LEAFREF_DEFAULT_CODEC;
+ }
+
+ final TypeDefinitionAwareCodec<Object, ? extends TypeDefinition<?>> codec = TypeDefinitionAwareCodec.from(type);
+ if (codec == null) {
+ LOG.debug("Codec for type \"{}\" is not implemented yet.", type.getQName().getLocalName());
+ return NULL_CODEC;
+ }
+
+ return codec;
+ }
+ });
+
+ private final Codec<?, ?> iidCodec;
+ private final Codec<?, ?> idrefCodec;
+
+ private CodecFactory(final SchemaContext context) {
+ iidCodec = new JSONStringInstanceIdentifierCodec(context);
+ idrefCodec = new JSONStringIdentityrefCodec(context);
+ }
+
+ public static CodecFactory create(final SchemaContext context) {
+ return new CodecFactory(context);
+ }
+
+ @SuppressWarnings("unchecked")
+ public final Codec<Object, Object> codecFor(final TypeDefinition<?> typeDefinition) {
+ return (Codec<Object, Object>) codecs.getUnchecked(typeDefinition);
+ }
+}
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
-import org.opendaylight.yangtools.yang.data.codec.gson.helpers.RestCodecFactory;
-import org.opendaylight.yangtools.yang.data.codec.gson.helpers.SchemaContextUtils;
import org.opendaylight.yangtools.yang.data.impl.codec.SchemaTracker;
import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode;
import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
private final Deque<TypeInfo> stack = new ArrayDeque<>();
private final SchemaContext schemaContext;
- private final SchemaContextUtils utils;
- private final RestCodecFactory codecs;
+ private final CodecFactory codecs;
private final SchemaTracker tracker;
private final Writer writer;
private final String indent;
indent = null;
}
- this.utils = SchemaContextUtils.create(schemaContext);
- this.codecs = RestCodecFactory.create(utils);
+ this.codecs = CodecFactory.create(schemaContext);
this.tracker = SchemaTracker.create(schemaContext);
}
--- /dev/null
+/*
+ * 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.yang.data.codec.gson;
+
+import com.google.common.base.Preconditions;
+
+import java.net.URI;
+
+import org.opendaylight.yangtools.yang.data.util.AbstractModuleStringIdentityrefCodec;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+final class JSONStringIdentityrefCodec extends AbstractModuleStringIdentityrefCodec {
+ private final SchemaContext context;
+
+ JSONStringIdentityrefCodec(final SchemaContext context) {
+ this.context = Preconditions.checkNotNull(context);
+ }
+
+ @Override
+ protected Module moduleForPrefix(final String prefix) {
+ return context.findModuleByName(prefix, null);
+ }
+
+ @Override
+ protected String prefixForNamespace(final URI namespace) {
+ final Module module = context.findModuleByNamespaceAndRevision(namespace, null);
+ return module == null ? null : module.getName();
+ }
+
+}
--- /dev/null
+/*
+ * 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.yang.data.codec.gson;
+
+import com.google.common.base.Preconditions;
+
+import java.net.URI;
+
+import org.opendaylight.yangtools.yang.data.util.AbstractModuleStringInstanceIdentifierCodec;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+final class JSONStringInstanceIdentifierCodec extends AbstractModuleStringInstanceIdentifierCodec {
+ private final SchemaContext context;
+
+ JSONStringInstanceIdentifierCodec(final SchemaContext context) {
+ this.context = Preconditions.checkNotNull(context);
+ }
+
+ @Override
+ protected Module moduleForPrefix(final String prefix) {
+ return context.findModuleByName(prefix, null);
+ }
+
+ @Override
+ protected String prefixForNamespace(final URI namespace) {
+ final Module module = context.findModuleByNamespaceAndRevision(namespace, null);
+ return module == null ? null : module.getName();
+ }
+}
import java.io.Flushable;
import java.io.IOException;
import java.net.URI;
-import java.security.InvalidParameterException;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
-import org.opendaylight.yangtools.yang.data.codec.gson.helpers.IdentityValuesDTO;
-import org.opendaylight.yangtools.yang.data.codec.gson.helpers.RestCodecFactory;
-import org.opendaylight.yangtools.yang.data.codec.gson.helpers.RestUtil;
-import org.opendaylight.yangtools.yang.data.codec.gson.helpers.RestUtil.PrefixMapingFromJson;
-import org.opendaylight.yangtools.yang.data.codec.gson.helpers.SchemaContextUtils;
import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode;
import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.Module;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
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;
/**
* This class parses JSON elements from a GSON JsonReader. It disallows multiple elements of the same name unlike the
public final class JsonParserStream implements Closeable, Flushable {
private final Deque<URI> namespaces = new ArrayDeque<>();
private final NormalizedNodeStreamWriter writer;
- private final SchemaContextUtils utils;
- private final RestCodecFactory codecs;
+ private final CodecFactory codecs;
private final SchemaContext schema;
private JsonParserStream(final NormalizedNodeStreamWriter writer, final SchemaContext schemaContext) {
this.schema = Preconditions.checkNotNull(schemaContext);
- this.utils = SchemaContextUtils.create(schemaContext);
this.writer = Preconditions.checkNotNull(writer);
- this.codecs = RestCodecFactory.create(utils);
+ this.codecs = CodecFactory.create(schemaContext);
}
public static JsonParserStream create(final NormalizedNodeStreamWriter writer, final SchemaContext schemaContext) {
return value;
}
- final Object inputValue;
- if (typeDefinition instanceof IdentityrefTypeDefinition) {
- inputValue = valueAsIdentityRef(value);
- } else if (typeDefinition instanceof InstanceIdentifierTypeDefinition) {
- inputValue = valueAsInstanceIdentifier(value);
- } else {
- inputValue = value;
- }
-
- return codecs.codecFor(typeDefinition).deserialize(inputValue);
+ return codecs.codecFor(typeDefinition).deserialize(value);
}
private static TypeDefinition<? extends Object> typeDefinition(final DataSchemaNode node) {
return baseType;
}
- private static Object valueAsInstanceIdentifier(final String value) {
- // it could be instance-identifier Built-In Type
- if (!value.isEmpty() && value.charAt(0) == '/') {
- IdentityValuesDTO resolvedValue = RestUtil.asInstanceIdentifier(value, new PrefixMapingFromJson());
- if (resolvedValue != null) {
- return resolvedValue;
- }
- }
- throw new InvalidParameterException("Value for instance-identifier doesn't have correct format");
- }
-
- private static IdentityValuesDTO valueAsIdentityRef(final String value) {
- // it could be identityref Built-In Type
- URI namespace = getNamespaceFor(value);
- if (namespace != null) {
- return new IdentityValuesDTO(namespace.toString(), getLocalNameFor(value), null, value);
- }
- throw new InvalidParameterException("Value for identityref has to be in format moduleName:localName.");
- }
-
- private static URI getNamespaceFor(final String jsonElementName) {
- // The string needs to me in form "moduleName:localName"
- final int idx = jsonElementName.indexOf(':');
- if (idx == -1 || jsonElementName.indexOf(':', idx + 1) != -1) {
- return null;
- }
-
- // FIXME: is this correct? This should be looking up module name instead
- return URI.create(jsonElementName.substring(0, idx));
- }
-
- private static String getLocalNameFor(final String jsonElementName) {
- // The string needs to me in form "moduleName:localName"
- final int idx = jsonElementName.indexOf(':');
- if (idx == -1 || jsonElementName.indexOf(':', idx + 1) != -1) {
- return jsonElementName;
- }
-
- return jsonElementName.substring(idx + 1);
- }
-
private void removeNamespace() {
namespaces.pop();
}
if (lastIndexOfColon != -1) {
moduleNamePart = childName.substring(0, lastIndexOfColon);
nodeNamePart = childName.substring(lastIndexOfColon + 1);
- namespace = utils.findNamespaceByModuleName(moduleNamePart);
+
+ final Module m = schema.findModuleByName(moduleNamePart, null);
+ namespace = m == null ? null : m.getNamespace();
} else {
nodeNamePart = childName;
}
+++ /dev/null
-/*
- * 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.yang.data.codec.gson.helpers;
-
-import com.google.common.base.Preconditions;
-
-import java.net.URI;
-
-import org.opendaylight.yangtools.yang.model.api.Module;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-abstract class AbstractCodecImpl {
- private static final Logger LOG = LoggerFactory.getLogger(AbstractCodecImpl.class);
- private final SchemaContextUtils schema;
-
- protected AbstractCodecImpl(final SchemaContextUtils schema) {
- this.schema = Preconditions.checkNotNull(schema);
- }
-
- protected final SchemaContextUtils getSchema() {
- return schema;
- }
-
- protected final Module getModuleByNamespace(final String namespace) {
- URI validNamespace = resolveValidNamespace(namespace);
-
- Module module = schema.findModuleByNamespace(validNamespace);
- if (module == null) {
- LOG.info("Module for namespace " + validNamespace + " wasn't found.");
- return null;
- }
- return module;
- }
-
- protected final URI resolveValidNamespace(final String namespace) {
- URI validNamespace = schema.findNamespaceByModuleName(namespace);
- if (validNamespace == null) {
- validNamespace = URI.create(namespace);
- }
-
- return validNamespace;
- }
-}
+++ /dev/null
-/*
- * 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.yang.data.codec.gson.helpers;
-
-import com.google.common.annotations.Beta;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-/**
- * This class is implementation-internal and subject to change. Please do not use it.
- */
-@Beta
-public final class IdentityValuesDTO {
-
- private final List<IdentityValue> elementData = new ArrayList<>();
- private final String originValue;
-
- public IdentityValuesDTO(final String namespace, final String value, final String prefix, final String originValue) {
- elementData.add(new IdentityValue(namespace, value, prefix));
- this.originValue = originValue;
- }
-
- public IdentityValuesDTO(final String originValue) {
- this.originValue = originValue;
- }
-
- public IdentityValuesDTO() {
- originValue = null;
- }
-
- public void add(final String namespace, final String value, final String prefix) {
- elementData.add(new IdentityValue(namespace, value, prefix));
- }
-
- public void add(final IdentityValue identityValue) {
- elementData.add(identityValue);
- }
-
- public List<IdentityValue> getValuesWithNamespaces() {
- return Collections.unmodifiableList(elementData);
- }
-
- @Override
- public String toString() {
- return elementData.toString();
- }
-
- public String getOriginValue() {
- return originValue;
- }
-
- public static final class IdentityValue {
-
- private final String namespace;
- private final String value;
- private final String prefix;
- private List<Predicate> predicates;
-
- public IdentityValue(final String namespace, final String value, final String prefix) {
- this.namespace = namespace;
- this.value = value;
- this.prefix = prefix;
- }
-
- public String getNamespace() {
- return namespace;
- }
-
- public String getValue() {
- return value;
- }
-
- public String getPrefix() {
- return prefix;
- }
-
- public List<Predicate> getPredicates() {
- if (predicates == null) {
- return Collections.emptyList();
- }
- return Collections.unmodifiableList(predicates);
- }
-
- public void setPredicates(final List<Predicate> predicates) {
- this.predicates = predicates;
- }
-
- @Override
- public String toString() {
- StringBuilder sb = new StringBuilder();
- if (namespace != null) {
- sb.append(namespace);
- }
- if (prefix != null) {
- sb.append("(").append(prefix).append(")");
- }
- if (value != null) {
- sb.append(" - ").append(value);
- }
- if (predicates != null && !predicates.isEmpty()) {
- for (Predicate predicate : predicates) {
- sb.append("[");
- predicate.toString();
- sb.append("]");
- }
- }
- return sb.toString();
- }
-
- }
-
- public static final class Predicate {
-
- private final IdentityValue name;
- private final String value;
-
- public Predicate(final IdentityValue name, final String value) {
- super();
- this.name = name;
- this.value = value;
- }
-
- public IdentityValue getName() {
- return name;
- }
-
- public String getValue() {
- return value;
- }
-
- @Override
- public String toString() {
- StringBuilder sb = new StringBuilder();
- if (name != null) {
- sb.append(name.toString());
- }
- if (value != null) {
- sb.append("=").append(value);
- }
- return sb.toString();
- }
-
- public boolean isLeafList() {
- return name == null ? true : false;
- }
-
- }
-}
+++ /dev/null
-/*
- * 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.yang.data.codec.gson.helpers;
-
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.codec.IdentityrefCodec;
-import org.opendaylight.yangtools.yang.data.codec.gson.helpers.IdentityValuesDTO.IdentityValue;
-import org.opendaylight.yangtools.yang.model.api.Module;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-class IdentityrefCodecImpl extends AbstractCodecImpl implements IdentityrefCodec<IdentityValuesDTO> {
- private static final Logger LOG = LoggerFactory.getLogger(IdentityrefCodecImpl.class);
-
- IdentityrefCodecImpl(final SchemaContextUtils schema) {
- super(schema);
- }
-
- @Override
- public IdentityValuesDTO serialize(final QName data) {
- return new IdentityValuesDTO(data.getNamespace().toString(), data.getLocalName(), data.getPrefix(), null);
- }
-
- @Override
- public QName deserialize(final IdentityValuesDTO data) {
- IdentityValue valueWithNamespace = data.getValuesWithNamespaces().get(0);
- Module module = getModuleByNamespace(valueWithNamespace.getNamespace());
- if (module == null) {
- LOG.info("Module was not found for namespace {}", valueWithNamespace.getNamespace());
- LOG.info("Idenetityref will be translated as NULL for data - {}", String.valueOf(valueWithNamespace));
- return null;
- }
-
- return QName.create(module.getNamespace(), module.getRevision(), valueWithNamespace.getValue());
- }
-
-}
\ No newline at end of file
+++ /dev/null
-/*
- * 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.yang.data.codec.gson.helpers;
-
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
-import org.opendaylight.yangtools.yang.data.api.codec.InstanceIdentifierCodec;
-import org.opendaylight.yangtools.yang.data.codec.gson.helpers.IdentityValuesDTO.IdentityValue;
-import org.opendaylight.yangtools.yang.data.codec.gson.helpers.IdentityValuesDTO.Predicate;
-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.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-class InstanceIdentifierCodecImpl extends AbstractCodecImpl implements InstanceIdentifierCodec<IdentityValuesDTO> {
- private static final Logger LOG = LoggerFactory.getLogger(InstanceIdentifierCodecImpl.class);
-
- InstanceIdentifierCodecImpl(final SchemaContextUtils schema) {
- super(schema);
- }
-
- @Override
- public IdentityValuesDTO serialize(final YangInstanceIdentifier data) {
- IdentityValuesDTO identityValuesDTO = new IdentityValuesDTO();
- for (PathArgument pathArgument : data.getPathArguments()) {
- IdentityValue identityValue = qNameToIdentityValue(pathArgument.getNodeType());
- if (pathArgument instanceof NodeIdentifierWithPredicates && identityValue != null) {
- List<Predicate> predicates = keyValuesToPredicateList(((NodeIdentifierWithPredicates) pathArgument)
- .getKeyValues());
- identityValue.setPredicates(predicates);
- } else if (pathArgument instanceof NodeWithValue && identityValue != null) {
- List<Predicate> 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 YangInstanceIdentifier deserialize(final IdentityValuesDTO data) {
- List<PathArgument> result = new ArrayList<PathArgument>();
- IdentityValue valueWithNamespace = data.getValuesWithNamespaces().get(0);
- Module module = getModuleByNamespace(valueWithNamespace.getNamespace());
- if (module == null) {
- LOG.info("Module by namespace '{}' of first node in instance-identiefier was not found.",
- valueWithNamespace.getNamespace());
- LOG.info("Instance-identifier will be translated as NULL for data - {}",
- String.valueOf(valueWithNamespace.getValue()));
- return null;
- }
-
- DataNodeContainer parentContainer = module;
- List<IdentityValue> identities = data.getValuesWithNamespaces();
- for (int i = 0; i < identities.size(); i++) {
- IdentityValue identityValue = identities.get(i);
- URI validNamespace = resolveValidNamespace(identityValue.getNamespace());
- DataSchemaNode node = getSchema().findInstanceDataChildByNameAndNamespace(
- parentContainer, identityValue.getValue(), validNamespace);
- if (node == null) {
- LOG.info("'{}' node was not found in {}", identityValue, parentContainer.getChildNodes());
- LOG.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()) {
- LOG.info("Predicate's data is not type of leaf-list. It should be in format \".='value'\"");
- LOG.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<QName, Object> predicatesMap = new HashMap<>();
- for (Predicate predicate : identityValue.getPredicates()) {
- validNamespace = resolveValidNamespace(predicate.getName().getNamespace());
- DataSchemaNode listKey = getSchema()
- .findInstanceDataChildByNameAndNamespace(listNode, predicate.getName().getValue(),
- validNamespace);
- predicatesMap.put(listKey.getQName(), predicate.getValue());
- }
- pathArgument = new NodeIdentifierWithPredicates(qName, predicatesMap);
- } else {
- LOG.info("Node {} is not List or Leaf-list.", node);
- LOG.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 {
- LOG.info("Node {} isn't instance of DataNodeContainer", node);
- LOG.info("Instance-identifier will be translated as NULL for data - {}",
- String.valueOf(identityValue.getValue()));
- return null;
- }
- }
- }
-
- return result.isEmpty() ? null : YangInstanceIdentifier.create(result);
- }
-
- private static List<Predicate> keyValuesToPredicateList(final Map<QName, Object> keyValues) {
- List<Predicate> result = new ArrayList<>(keyValues.size());
- for (Map.Entry<QName, Object> e : keyValues.entrySet()) {
- result.add(new Predicate(qNameToIdentityValue(e.getKey()), String.valueOf(e.getValue())));
- }
- return result;
- }
-
- private static IdentityValue qNameToIdentityValue(final QName qName) {
- if (qName != null) {
- // FIXME: the prefix here is completely arbitrary
- return new IdentityValue(qName.getNamespace().toString(), qName.getLocalName(), qName.getPrefix());
- }
- return null;
- }
-}
+++ /dev/null
-/*
- * 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.yang.data.codec.gson.helpers;
-
-import org.opendaylight.yangtools.yang.data.api.codec.LeafrefCodec;
-
-class LeafrefCodecImpl implements LeafrefCodec<String> {
-
- @Override
- public String serialize(final Object data) {
- return String.valueOf(data);
- }
-
- @Override
- public Object deserialize(final String data) {
- return data;
- }
-
-}
\ No newline at end of file
+++ /dev/null
-/*
- * 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.yang.data.codec.gson.helpers;
-
-import org.opendaylight.yangtools.concepts.Codec;
-import org.opendaylight.yangtools.yang.data.impl.codec.TypeDefinitionAwareCodec;
-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;
-
-@SuppressWarnings("rawtypes")
-final class ObjectCodec extends AbstractCodecImpl implements Codec<Object, Object> {
- public static final Codec LEAFREF_DEFAULT_CODEC = new LeafrefCodecImpl();
- private static final Logger LOG = LoggerFactory.getLogger(RestCodecFactory.class);
- private final Codec instanceIdentifier;
- private final Codec identityrefCodec;
- private final TypeDefinition<?> type;
-
- ObjectCodec(final SchemaContextUtils schema, final TypeDefinition<?> typeDefinition) {
- super(schema);
- type = RestUtil.resolveBaseTypeFrom(typeDefinition);
- if (type instanceof IdentityrefTypeDefinition) {
- identityrefCodec = new IdentityrefCodecImpl(schema);
- } else {
- identityrefCodec = null;
- }
- if (type instanceof InstanceIdentifierTypeDefinition) {
- instanceIdentifier = new InstanceIdentifierCodecImpl(schema);
- } else {
- instanceIdentifier = null;
- }
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public Object deserialize(final Object input) {
- try {
- if (type instanceof IdentityrefTypeDefinition) {
- if (input instanceof IdentityValuesDTO) {
- return identityrefCodec.deserialize(input);
- }
- LOG.debug("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);
- }
- LOG.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<Object, ? extends TypeDefinition<?>> typeAwarecodec = TypeDefinitionAwareCodec
- .from(type);
- if (typeAwarecodec != null) {
- if (input instanceof IdentityValuesDTO) {
- return typeAwarecodec.deserialize(((IdentityValuesDTO) input).getOriginValue());
- }
- return typeAwarecodec.deserialize(String.valueOf(input));
- } else {
- LOG.debug("Codec for type \"" + type.getQName().getLocalName()
- + "\" is not implemented yet.");
- return null;
- }
- }
- } catch (ClassCastException e) {
- // TODO remove this catch when everyone use codecs
- LOG.error("ClassCastException was thrown when codec is invoked with parameter " + String.valueOf(input),
- e);
- return null;
- }
- }
-
- @SuppressWarnings("unchecked")
- @Override
- public Object serialize(final Object input) {
- try {
- if (type instanceof IdentityrefTypeDefinition) {
- 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<Object, ? extends TypeDefinition<?>> typeAwarecodec = TypeDefinitionAwareCodec
- .from(type);
- if (typeAwarecodec != null) {
- return typeAwarecodec.serialize(input);
- } else {
- LOG.debug("Codec for type \"" + type.getQName().getLocalName()
- + "\" is not implemented yet.");
- return null;
- }
- }
- } catch (ClassCastException e) { // TODO remove this catch when everyone use codecs
- LOG.error(
- "ClassCastException was thrown when codec is invoked with parameter " + String.valueOf(input),
- e);
- return input;
- }
- }
-
-}
\ No newline at end of file
+++ /dev/null
-/*
- * 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.yang.data.codec.gson.helpers;
-
-import com.google.common.annotations.Beta;
-import com.google.common.base.Preconditions;
-import com.google.common.cache.CacheBuilder;
-import com.google.common.cache.CacheLoader;
-import com.google.common.cache.LoadingCache;
-
-import org.opendaylight.yangtools.concepts.Codec;
-import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
-
-/**
- * This class is implementation-internal and subject to change. Please do not use it.
- */
-@Beta
-public final class RestCodecFactory {
- private final LoadingCache<TypeDefinition<?>, Codec<Object, Object>> codecs =
- CacheBuilder.newBuilder().softValues().build(new CacheLoader<TypeDefinition<?>, Codec<Object, Object>>() {
- @Override
- public Codec<Object, Object> load(final TypeDefinition<?> key) throws Exception {
- return new ObjectCodec(utils, key);
- }
- });
- private final SchemaContextUtils utils;
-
- private RestCodecFactory(final SchemaContextUtils utils) {
- this.utils = Preconditions.checkNotNull(utils);
- }
-
- public static RestCodecFactory create(final SchemaContextUtils utils) {
- return new RestCodecFactory(utils);
- }
-
- public final Codec<Object, Object> codecFor(final TypeDefinition<?> typeDefinition) {
- return codecs.getUnchecked(typeDefinition);
- }
-}
+++ /dev/null
-/*
- * 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.yang.data.codec.gson.helpers;
-
-
-import com.google.common.annotations.Beta;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import javax.xml.stream.events.StartElement;
-
-import org.opendaylight.yangtools.yang.data.codec.gson.helpers.IdentityValuesDTO.IdentityValue;
-import org.opendaylight.yangtools.yang.data.codec.gson.helpers.IdentityValuesDTO.Predicate;
-import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
-
-/**
- * This class is implementation-internal and subject to change. Please do not use it.
- */
-@Beta
-public final class RestUtil {
-
- // FIXME: BUG-1275: this is code duplicates data.impl.codec
-
- public static final String SQUOTE = "'";
- public static final String DQUOTE = "\"";
- private static final Pattern PREDICATE_PATTERN = Pattern.compile("\\[(.*?)\\]");
-
- public final static TypeDefinition<?> resolveBaseTypeFrom(final TypeDefinition<?> type) {
- TypeDefinition<?> superType = type;
- while (superType.getBaseType() != null) {
- superType = superType.getBaseType();
- }
- return superType;
- }
-
- public static IdentityValuesDTO asInstanceIdentifier(final String value, final PrefixesMaping prefixMap) {
- String valueTrimmed = value.trim();
- if (!valueTrimmed.startsWith("/")) {
- return null;
- }
- String[] xPathParts = valueTrimmed.split("/");
- if (xPathParts.length < 2) { // must be at least "/pr:node"
- return null;
- }
- IdentityValuesDTO identityValuesDTO = new IdentityValuesDTO(value);
- for (int i = 1; i < xPathParts.length; i++) {
- String xPathPartTrimmed = xPathParts[i].trim();
-
- String xPathPartStr = getIdAndPrefixAsStr(xPathPartTrimmed);
- IdentityValue identityValue = toIdentity(xPathPartStr, prefixMap);
- if (identityValue == null) {
- return null;
- }
-
- List<Predicate> predicates = toPredicates(xPathPartTrimmed, prefixMap);
- if (predicates == null) {
- return null;
- }
- identityValue.setPredicates(predicates);
-
- identityValuesDTO.add(identityValue);
- }
- return identityValuesDTO.getValuesWithNamespaces().isEmpty() ? null : identityValuesDTO;
- }
-
- private static String getIdAndPrefixAsStr(final String pathPart) {
- int predicateStartIndex = pathPart.indexOf("[");
- return predicateStartIndex == -1 ? pathPart : pathPart.substring(0, predicateStartIndex);
- }
-
- private static IdentityValue toIdentity(final String xPathPart, final PrefixesMaping prefixMap) {
- String xPathPartTrimmed = xPathPart.trim();
- if (xPathPartTrimmed.isEmpty()) {
- return null;
- }
- String[] prefixAndIdentifier = xPathPartTrimmed.split(":");
- // it is not "prefix:value"
- if (prefixAndIdentifier.length != 2) {
- return null;
- }
- String prefix = prefixAndIdentifier[0].trim();
- String identifier = prefixAndIdentifier[1].trim();
- if (prefix.isEmpty() || identifier.isEmpty()) {
- return null;
- }
- String namespace = prefixMap.getNamespace(prefix);
- return new IdentityValue(namespace, identifier, namespace.equals(prefix) ? null : prefix);
- }
-
- private static List<Predicate> toPredicates(final String predicatesStr, final PrefixesMaping prefixMap) {
- List<Predicate> result = new ArrayList<>();
- List<String> predicates = new ArrayList<>();
- Matcher matcher = PREDICATE_PATTERN.matcher(predicatesStr);
- while (matcher.find()) {
- predicates.add(matcher.group(1).trim());
- }
- for (String predicate : predicates) {
- int indexOfEqualityMark = predicate.indexOf("=");
- if (indexOfEqualityMark != -1) {
- String predicateValue = toPredicateValue(predicate.substring(indexOfEqualityMark + 1));
- if (predicate.startsWith(".")) { // it is leaf-list
- if (predicateValue == null) {
- return null;
- }
- result.add(new Predicate(null, predicateValue));
- } else {
- IdentityValue identityValue = toIdentity(predicate.substring(0, indexOfEqualityMark), prefixMap);
- if (identityValue == null || predicateValue == null) {
- return null;
- }
- result.add(new Predicate(identityValue, predicateValue));
- }
- }
- }
- return result;
- }
-
- private static String toPredicateValue(final String predicatedValue) {
- String predicatedValueTrimmed = predicatedValue.trim();
- if ((predicatedValueTrimmed.startsWith(DQUOTE) || predicatedValueTrimmed.startsWith(SQUOTE))
- && (predicatedValueTrimmed.endsWith(DQUOTE) || predicatedValueTrimmed.endsWith(SQUOTE))) {
- return predicatedValueTrimmed.substring(1, predicatedValueTrimmed.length() - 1);
- }
- return null;
- }
-
- public interface PrefixesMaping {
- public String getNamespace(String prefix);
- }
-
- public static class PrefixMapingFromXml implements PrefixesMaping {
- StartElement startElement = null;
-
- public PrefixMapingFromXml(final StartElement startElement) {
- this.startElement = startElement;
- }
-
- @Override
- public String getNamespace(final String prefix) {
- return startElement.getNamespaceContext().getNamespaceURI(prefix);
- }
- }
-
- public static class PrefixMapingFromJson implements PrefixesMaping {
-
- @Override
- public String getNamespace(final String prefix) {
- return prefix;
- }
- }
-
-}
+++ /dev/null
-/*
- * 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.yang.data.codec.gson.helpers;
-
-import com.google.common.annotations.Beta;
-import com.google.common.base.Function;
-import com.google.common.base.Objects;
-import com.google.common.base.Preconditions;
-import com.google.common.base.Predicate;
-import com.google.common.collect.Iterables;
-
-import java.net.URI;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Set;
-
-import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
-import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
-import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
-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.LeafSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
-import org.opendaylight.yangtools.yang.model.api.Module;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-
-/**
- * This class is implementation-internal and subject to change. Please do not use it.
- */
-@Beta
-public final class SchemaContextUtils {
- private final SchemaContext schemaContext;
-
- private SchemaContextUtils(final SchemaContext schemaContext) {
- this.schemaContext = Preconditions.checkNotNull(schemaContext);
- }
-
- public static SchemaContextUtils create(final SchemaContext schemaContext) {
- return new SchemaContextUtils(schemaContext);
- }
-
- public URI findNamespaceByModuleName(final String moduleName) {
- final Module module = this.findModuleByName(moduleName);
- return module == null ? null : module.getNamespace();
- }
-
-
- public Module findModuleByName(final String moduleName) {
- checkPreconditions();
- Preconditions.checkArgument(moduleName != null && !moduleName.isEmpty());
- return schemaContext.findModuleByName(moduleName, null);
- }
-
- public Module findModuleByNamespace(final URI namespace) {
- this.checkPreconditions();
- Preconditions.checkArgument(namespace != null);
- return schemaContext.findModuleByNamespaceAndRevision(namespace, null);
- }
-
- private void checkPreconditions() {
- if (schemaContext == null) {
- throw new IllegalStateException("Schema context isn't set.");
- }
- }
-
- public DataSchemaNode findInstanceDataChildByNameAndNamespace(final DataNodeContainer container, final String name,
- final URI namespace) {
- Preconditions.<URI> checkNotNull(namespace);
-
- final List<DataSchemaNode> potentialSchemaNodes = findInstanceDataChildrenByName(container, name);
-
- Predicate<DataSchemaNode> filter = new Predicate<DataSchemaNode>() {
- @Override
- public boolean apply(final DataSchemaNode node) {
- return Objects.equal(node.getQName().getNamespace(), namespace);
- }
- };
-
- Iterable<DataSchemaNode> result = Iterables.filter(potentialSchemaNodes, filter);
- return Iterables.getFirst(result, null);
- }
-
- public List<DataSchemaNode> findInstanceDataChildrenByName(final DataNodeContainer container, final String name) {
- Preconditions.<DataNodeContainer> checkNotNull(container);
- Preconditions.<String> checkNotNull(name);
-
- List<DataSchemaNode> instantiatedDataNodeContainers = new ArrayList<DataSchemaNode>();
- collectInstanceDataNodeContainers(instantiatedDataNodeContainers, container, name);
- return instantiatedDataNodeContainers;
- }
-
- private void collectInstanceDataNodeContainers(final List<DataSchemaNode> potentialSchemaNodes,
- final DataNodeContainer container, final String name) {
-
- Predicate<DataSchemaNode> filter = new Predicate<DataSchemaNode>() {
- @Override
- public boolean apply(final DataSchemaNode node) {
- return Objects.equal(node.getQName().getLocalName(), name);
- }
- };
-
- Iterable<DataSchemaNode> nodes = Iterables.filter(container.getChildNodes(), filter);
-
- // Can't combine this loop with the filter above because the filter is
- // lazily-applied by Iterables.filter.
- for (final DataSchemaNode potentialNode : nodes) {
- if (isInstantiatedDataSchema(potentialNode)) {
- potentialSchemaNodes.add(potentialNode);
- }
- }
-
- Iterable<ChoiceNode> choiceNodes = Iterables.filter(container.getChildNodes(), ChoiceNode.class);
- Iterable<Set<ChoiceCaseNode>> map = Iterables.transform(choiceNodes, CHOICE_FUNCTION);
-
- final Iterable<ChoiceCaseNode> allCases = Iterables.<ChoiceCaseNode> concat(map);
- for (final ChoiceCaseNode caze : allCases) {
- collectInstanceDataNodeContainers(potentialSchemaNodes, caze, name);
- }
- }
-
- public boolean isInstantiatedDataSchema(final DataSchemaNode node) {
- return node instanceof LeafSchemaNode || node instanceof LeafListSchemaNode
- || node instanceof ContainerSchemaNode || node instanceof ListSchemaNode
- || node instanceof AnyXmlSchemaNode;
- }
-
- private final Function<ChoiceNode, Set<ChoiceCaseNode>> CHOICE_FUNCTION = new Function<ChoiceNode, Set<ChoiceCaseNode>>() {
- @Override
- public Set<ChoiceCaseNode> apply(final ChoiceNode node) {
- return node.getCases();
- }
- };
-
-}
--- /dev/null
+/*
+ * 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.yang.data.util;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Preconditions;
+
+import javax.annotation.Nonnull;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.Module;
+
+@Beta
+public abstract class AbstractModuleStringIdentityrefCodec extends AbstractStringIdentityrefCodec {
+ /**
+ * Resolve a string prefix into the corresponding module.
+ *
+ * @param prefix
+ * @return module mapped to prefix, or null if the module cannot be resolved
+ */
+ protected abstract Module moduleForPrefix(@Nonnull String prefix);
+
+ @Override
+ protected final QName createQName(final String prefix, final String localName) {
+ final Module module = moduleForPrefix(prefix);
+ Preconditions.checkArgument(module != null, "Failed to lookup prefix %s", prefix);
+ return QName.create(module.getQNameModule(), localName);
+ }
+}
--- /dev/null
+/*
+ * 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.yang.data.util;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Preconditions;
+
+import javax.annotation.Nonnull;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.Module;
+
+/**
+ * Extension of {@link AbstractStringInstanceIdentifierCodec}, which instantiates
+ * QNames by first resolving the namespace and then looking the target namespace
+ * in the list of currently-subscribed modules.
+ */
+@Beta
+public abstract class AbstractModuleStringInstanceIdentifierCodec extends AbstractStringInstanceIdentifierCodec {
+ /**
+ * Resolve a string prefix into the corresponding module.
+ *
+ * @param prefix
+ * @return module mapped to prefix, or null if the module cannot be resolved
+ */
+ protected abstract Module moduleForPrefix(@Nonnull String prefix);
+
+ @Override
+ protected final QName createQName(final String prefix, final String localName) {
+ final Module module = moduleForPrefix(prefix);
+ Preconditions.checkArgument(module != null, "Failed to lookup prefix %s", prefix);
+ return QName.create(module.getQNameModule(), localName);
+ }
+}
--- /dev/null
+/*
+ * 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.yang.data.util;
+
+import com.google.common.base.Preconditions;
+import com.google.common.base.Splitter;
+
+import java.net.URI;
+import java.util.Iterator;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import org.opendaylight.yangtools.yang.common.QName;
+
+abstract class AbstractNamespaceCodec {
+ private static final Splitter COLON_SPLITTER = Splitter.on(':');
+
+ /**
+ * Return string prefix for a particular namespace, allocating a new one if necessary.
+ *
+ * @param namespace Namespace to map
+ * @return Allocated unique prefix, or null if the prefix cannot be mapped.
+ */
+ protected abstract @Nullable String prefixForNamespace(final @Nonnull URI namespace);
+
+ /**
+ * Create a QName for a prefix and local name.
+ *
+ * @param prefix Prefix for namespace
+ * @param localName local name
+ * @return QName
+ * @throws IllegalArgumentException if the prefix cannot be resolved
+ */
+ protected abstract @Nullable QName createQName(final @Nonnull String prefix, final @Nonnull String localName);
+
+ private static String getIdAndPrefixAsStr(final String pathPart) {
+ int predicateStartIndex = pathPart.indexOf('[');
+ return predicateStartIndex == -1 ? pathPart : pathPart.substring(0, predicateStartIndex);
+ }
+
+ protected final StringBuilder appendQName(final StringBuilder sb, final QName qname) {
+ final String prefix = prefixForNamespace(qname.getNamespace());
+ Preconditions.checkArgument(prefix != null, "Failed to map QName {}", qname);
+ sb.append(prefix);
+ sb.append(':');
+ sb.append(qname.getLocalName());
+ return sb;
+ }
+
+ protected final QName parseQName(final String str) {
+ final String xPathPartTrimmed = getIdAndPrefixAsStr(str).trim();
+ final Iterator<String> it = COLON_SPLITTER.split(xPathPartTrimmed).iterator();
+
+ // Empty string
+ if (!it.hasNext()) {
+ return null;
+ }
+
+ final String prefix = it.next().trim();
+ if (prefix.isEmpty()) {
+ return null;
+ }
+
+ // it is not "prefix:value"
+ if (!it.hasNext()) {
+ return null;
+ }
+
+ final String identifier = it.next().trim();
+ if (identifier.isEmpty()) {
+ return null;
+ }
+
+ return createQName(prefix, identifier);
+ }
+}
--- /dev/null
+/*
+ * 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.yang.data.util;
+
+import com.google.common.annotations.Beta;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.codec.IdentityrefCodec;
+
+/**
+ * Abstract utility class for representations which encode Identityref as a
+ * prefix:name tuple. Typical uses are RESTCONF/JSON (module:name) and XML (prefix:name).
+ */
+@Beta
+public abstract class AbstractStringIdentityrefCodec extends AbstractNamespaceCodec implements IdentityrefCodec<String> {
+ @Override
+ public String serialize(final QName data) {
+ return appendQName(new StringBuilder(), data).toString();
+ }
+
+ @Override
+ public QName deserialize(final String data) {
+ return parseQName(data);
+ }
+}
--- /dev/null
+/*
+ * 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.yang.data.util;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Preconditions;
+import com.google.common.base.Splitter;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.codec.InstanceIdentifierCodec;
+
+/**
+ * Abstract utility class for representations which encode {@link YangInstanceIdentifier} as a
+ * prefix:name tuple. Typical uses are RESTCONF/JSON (module:name) and XML (prefix:name).
+ */
+@Beta
+public abstract class AbstractStringInstanceIdentifierCodec extends AbstractNamespaceCodec implements InstanceIdentifierCodec<String> {
+ private static final Pattern PREDICATE_PATTERN = Pattern.compile("\\[(.*?)\\]");
+ private static final Splitter SLASH_SPLITTER = Splitter.on('/');
+
+ @Override
+ public final String serialize(final YangInstanceIdentifier data) {
+ StringBuilder sb = new StringBuilder();
+ for (PathArgument arg : data.getPathArguments()) {
+ sb.append('/');
+ appendQName(sb, arg.getNodeType());
+
+ if (arg instanceof NodeIdentifierWithPredicates) {
+ for (Map.Entry<QName, Object> entry : ((NodeIdentifierWithPredicates) arg).getKeyValues().entrySet()) {
+ sb.append('[');
+ appendQName(sb, entry.getKey());
+ sb.append("='");
+ sb.append(String.valueOf(entry.getValue()));
+ sb.append("']");
+ }
+ } else if (arg instanceof NodeWithValue) {
+ sb.append("[.='");
+ sb.append(((NodeWithValue) arg).getValue());
+ sb.append("']");
+ }
+ }
+
+ return sb.toString();
+ }
+
+ @Override
+ public final YangInstanceIdentifier deserialize(final String data) {
+ Preconditions.checkNotNull(data, "Data may not be null");
+
+ final Iterator<String> xPathParts = SLASH_SPLITTER.split(data).iterator();
+
+ // must be at least "/pr:node"
+ if (!xPathParts.hasNext() || !xPathParts.next().isEmpty() || !xPathParts.hasNext()) {
+ return null;
+ }
+
+ List<PathArgument> result = new ArrayList<>();
+ while (xPathParts.hasNext()) {
+ String xPathPartTrimmed = xPathParts.next().trim();
+
+ PathArgument pathArgument = toPathArgument(xPathPartTrimmed);
+ if (pathArgument != null) {
+ result.add(pathArgument);
+ }
+ }
+ return YangInstanceIdentifier.create(result);
+ }
+
+ private PathArgument toPathArgument(final String xPathArgument) {
+ final QName mainQName = parseQName(xPathArgument);
+
+ // predicates
+ final Matcher matcher = PREDICATE_PATTERN.matcher(xPathArgument);
+ final Map<QName, Object> predicates = new HashMap<>();
+ QName currentQName = mainQName;
+
+ while (matcher.find()) {
+ final String predicateStr = matcher.group(1).trim();
+ final int indexOfEqualityMark = predicateStr.indexOf('=');
+ if (indexOfEqualityMark != -1) {
+ final String predicateValue = toPredicateValue(predicateStr.substring(indexOfEqualityMark + 1));
+ if (predicateValue == null) {
+ return null;
+ }
+
+ if (predicateStr.charAt(0) != '.') {
+ // target is not a leaf-list
+ currentQName = parseQName(predicateStr.substring(0, indexOfEqualityMark));
+ if (currentQName == null) {
+ return null;
+ }
+ }
+ predicates.put(currentQName, predicateValue);
+ }
+ }
+
+ if (predicates.isEmpty()) {
+ return new YangInstanceIdentifier.NodeIdentifier(mainQName);
+ } else {
+ return new YangInstanceIdentifier.NodeIdentifierWithPredicates(mainQName, predicates);
+ }
+ }
+
+ private static String toPredicateValue(final String predicatedValue) {
+ final String predicatedValueTrimmed = predicatedValue.trim();
+ if (predicatedValue.isEmpty()) {
+ return null;
+ }
+
+ switch (predicatedValueTrimmed.charAt(0)) {
+ case '"':
+ return trimIfEndIs(predicatedValueTrimmed, '"');
+ case '\'':
+ return trimIfEndIs(predicatedValueTrimmed, '\'');
+ default:
+ return null;
+ }
+ }
+
+ private static String trimIfEndIs(final String str, final char end) {
+ final int l = str.length() - 1;
+ if (str.charAt(l) != end) {
+ return null;
+ }
+
+ return str.substring(1, l);
+ }
+}