import java.util.Optional;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.common.QNameModule;
+import org.opendaylight.yangtools.yang.data.util.codec.IdentityCodecUtil;
import org.opendaylight.yangtools.yang.data.util.codec.QNameCodecUtil;
import org.opendaylight.yangtools.yang.model.api.Module;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
@Override
public QName parseValue(final Object ctx, final String value) {
- return QNameCodecUtil.decodeQName(value, prefix -> {
+ return IdentityCodecUtil.parseIdentity(value, schemaContext, prefix -> {
if (prefix.isEmpty()) {
return parentModule;
}
final Iterator<Module> modules = schemaContext.findModules(prefix).iterator();
checkArgument(modules.hasNext(), "Could not find module %s", prefix);
return modules.next().getQNameModule();
- });
+ }).getQName();
}
/**
assertEquals("lf15_21 value", lf15_21.getAsString());
assertEquals("lf13 value", lf13.getAsString());
assertTrue("one two".equals(lf15_11.getAsString()) || "two one".equals(lf15_11.getAsString()));
- assertEquals("complexjson:lf11", lf15_12.getAsString());
+ assertEquals("complexjson:ident", lf15_12.getAsString());
}
/**
assertEquals("lf15_12 value from augmentation", lf15_12Augment.getAsString());
assertEquals("lf13 value", lf13.getAsString());
assertTrue("one two".equals(lf15_11.getAsString()) || "two one".equals(lf15_11.getAsString()));
- assertEquals("complexjson:lf11", lf15_12.getAsString());
+ assertEquals("complexjson:ident", lf15_12.getAsString());
}
/**
private static LeafNode<Object> lf15_12Node() {
return Builders.leafBuilder()
.withNodeIdentifier(new NodeIdentifier(QName.create("ns:complex:json", "2014-08-11", "lf15_12")))
- .withValue(QName.create("ns:complex:json", "2014-08-11", "lf11")).build();
+ .withValue(QName.create("ns:complex:json", "2014-08-11", "ident")).build();
}
private static LeafNode<Object> lf15_11Node() {
"lf15_11" : "one two",
"lf13" : "lf13 value",
"lf15_21" : "lf15_21 value",
- "lf15_12" : "complexjson:lf11"
+ "lf15_12" : "complexjson:ident"
}
}
"lf15_11" : "one two",
"lf13" : "lf13 value",
"complexjson-augmentation:lf15_12" : "lf15_12 value from augmentation",
- "lf15_12" : "complexjson:lf11"
+ "lf15_12" : "complexjson:ident"
}
}
"complexjson-augmentation:lf15_11" : "lf15_11 value from augmentation",
"complexjson-augmentation:lf15_12" : "lf15_12 value from augmentation",
"lf15_11" : "one two",
- "lf15_12" : "complexjson:lf11",
+ "lf15_12" : "complexjson:ident",
"lf15_21" : "lf15_21 value",
"lf17" : "lf17 value",
* 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.xml;
import static com.google.common.base.Preconditions.checkArgument;
import javax.xml.stream.XMLStreamWriter;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.common.QNameModule;
+import org.opendaylight.yangtools.yang.data.util.codec.IdentityCodecUtil;
import org.opendaylight.yangtools.yang.data.util.codec.QNameCodecUtil;
import org.opendaylight.yangtools.yang.model.api.Module;
import org.opendaylight.yangtools.yang.model.api.SchemaContext;
@Override
public QName parseValue(final NamespaceContext ctx, final String str) {
- return QNameCodecUtil.decodeQName(str, prefix -> {
+ return IdentityCodecUtil.parseIdentity(str, schemaContext, prefix -> {
if (prefix.isEmpty()) {
return parentModule;
}
final Iterator<Module> modules = schemaContext.findModules(URI.create(prefixedNS)).iterator();
checkArgument(modules.hasNext(), "Could not find module for namespace %s", prefixedNS);
return modules.next().getQNameModule();
- });
+ }).getQName();
}
@Override
<groupId>${project.groupId}</groupId>
<artifactId>yang-model-util</artifactId>
</dependency>
+
+ <!-- Test dependencies -->
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>yang-test-util</artifactId>
+ </dependency>
</dependencies>
<build>
--- /dev/null
+/*
+ * Copyright (c) 2018 Pantheon Technologies, s.r.o. 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.codec;
+
+import static com.google.common.base.Preconditions.checkState;
+
+import com.google.common.annotations.Beta;
+import java.util.Optional;
+import java.util.function.Function;
+import javax.annotation.concurrent.ThreadSafe;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.QNameModule;
+import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+
+/**
+ * Utility methods for implementing string-to-identity codecs.
+ *
+ * @author Robert Varga
+ */
+@Beta
+@NonNullByDefault
+@ThreadSafe
+public final class IdentityCodecUtil {
+
+ private IdentityCodecUtil() {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Parse a string into a QName using specified prefix-to-QNameModule mapping function, interpreting the result
+ * as an IdentitySchemaNode existing in specified SchemaContext.
+ *
+ * @param value string value to parse
+ * @param schemaContext Parent schema context
+ * @param prefixToModule prefix-to-QNameModule mapping function
+ * @return Corresponding IdentitySchemaNode.
+ * @throws IllegalArgumentException if the value is invalid or does not refer to an existing identity
+ */
+ public static IdentitySchemaNode parseIdentity(final String value, final SchemaContext schemaContext,
+ final Function<String, QNameModule> prefixToModule) {
+ final QName qname = QNameCodecUtil.decodeQName(value, prefixToModule);
+ final Optional<Module> optModule = schemaContext.findModule(qname.getModule());
+ checkState(optModule.isPresent(), "Parsed QName %s refers to a non-existent module", qname);
+
+ for (IdentitySchemaNode identity : optModule.get().getIdentities()) {
+ if (qname.equals(identity.getQName())) {
+ return identity;
+ }
+ }
+
+ throw new IllegalArgumentException("Parsed QName " + qname + " does not refer to a valid identity");
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2018 Pantheon Technologies, s.r.o. 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.codec;
+
+import static com.google.common.base.Preconditions.checkState;
+import static org.junit.Assert.assertNotNull;
+
+import java.net.URI;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.opendaylight.yangtools.yang.common.QNameModule;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
+
+public class IdentityCodecUtilTest {
+ private static final QNameModule MODULE = QNameModule.create(URI.create("yangtools846"));
+ private static SchemaContext SCHEMA_CONTEXT;
+
+ @BeforeClass
+ public static void init() {
+ SCHEMA_CONTEXT = YangParserTestUtils.parseYangResource("/yangtools846.yang");
+ }
+
+ @AfterClass
+ public static void cleanup() {
+ SCHEMA_CONTEXT = null;
+ }
+
+ @Test
+ public void testCorrectInput() {
+ assertNotNull(IdentityCodecUtil.parseIdentity("yt846:foo", SCHEMA_CONTEXT,
+ IdentityCodecUtilTest::resolvePrefix));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testNonExistent() {
+ IdentityCodecUtil.parseIdentity("yt846:bar", SCHEMA_CONTEXT, IdentityCodecUtilTest::resolvePrefix);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testEmptyLocalName() {
+ IdentityCodecUtil.parseIdentity("yt846:", SCHEMA_CONTEXT, IdentityCodecUtilTest::resolvePrefix);
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void testEmptyString() {
+ IdentityCodecUtil.parseIdentity("", SCHEMA_CONTEXT, IdentityCodecUtilTest::resolvePrefix);
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void testNoPrefix() {
+ IdentityCodecUtil.parseIdentity("foo", SCHEMA_CONTEXT, IdentityCodecUtilTest::resolvePrefix);
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void testEmptyPrefix() {
+ IdentityCodecUtil.parseIdentity(":foo", SCHEMA_CONTEXT, IdentityCodecUtilTest::resolvePrefix);
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void testColon() {
+ IdentityCodecUtil.parseIdentity(":", SCHEMA_CONTEXT, IdentityCodecUtilTest::resolvePrefix);
+ }
+
+
+ private static QNameModule resolvePrefix(final String prefix) {
+ // TODO: QNameCodecUtil should deal with some of the malformed stuff here by throwing IAE. We throw an ISE
+ // to discern what is happening.
+ checkState("yt846".equals(prefix), "Unexpected prefix %s", prefix);
+ return MODULE;
+ }
+}
--- /dev/null
+module yangtools846 {
+ namespace "yangtools846";
+ prefix yt846;
+
+ identity foo;
+}
+