package org.opendaylight.restconf.nb.rfc8040.utils.parser;
import static java.util.Objects.requireNonNull;
-import static org.opendaylight.restconf.nb.rfc8040.utils.RestconfConstants.SLASH;
import com.google.common.base.CharMatcher;
import com.google.common.collect.ImmutableList;
import org.opendaylight.yangtools.yang.data.util.DataSchemaContextTree;
import org.opendaylight.yangtools.yang.model.api.ActionDefinition;
import org.opendaylight.yangtools.yang.model.api.ActionNodeContainer;
-import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ContainerLike;
import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.EffectiveModelContext;
import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode;
import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
// percent encoded radix for parsing integers
private static final int PERCENT_ENCODED_RADIX = 16;
- private final SchemaContext schemaContext;
+ private final EffectiveModelContext schemaContext;
private final String data;
private DataSchemaContextNode<?> current;
private int offset;
- private YangInstanceIdentifierDeserializer(final SchemaContext schemaContext, final String data) {
+ private YangInstanceIdentifierDeserializer(final EffectiveModelContext schemaContext, final String data) {
this.schemaContext = requireNonNull(schemaContext);
this.data = requireNonNull(data);
current = DataSchemaContextTree.from(schemaContext).getRoot();
* @param data path to data, in URL string form
* @return {@link Iterable} of {@link PathArgument}
*/
- public static Iterable<PathArgument> create(final SchemaContext schemaContext, final String data) {
+ public static Iterable<PathArgument> create(final EffectiveModelContext schemaContext, final String data) {
return new YangInstanceIdentifierDeserializer(schemaContext, data).parse();
}
final QName qname = prepareQName();
// this is the last identifier (input is consumed) or end of identifier (slash)
- if (allCharsConsumed() || currentChar() == SLASH) {
+ if (allCharsConsumed() || currentChar() == '/') {
prepareIdentifier(qname, path);
path.add(current == null ? NodeIdentifier.create(qname) : current.getIdentifier());
} else if (currentChar() == '=') {
skipCurrentChar();
// read key value separated by comma
- while (keys.hasNext() && !allCharsConsumed() && currentChar() != SLASH) {
+ while (keys.hasNext() && !allCharsConsumed() && currentChar() != '/') {
// empty key value
if (currentChar() == ',') {
// parse value
final QName key = keys.next();
Optional<DataSchemaNode> leafSchemaNode = listSchemaNode.findDataChildByName(key);
- RestconfDocumentedException.throwIf(!leafSchemaNode.isPresent(), ErrorType.PROTOCOL, ErrorTag.BAD_ELEMENT,
+ RestconfDocumentedException.throwIf(leafSchemaNode.isEmpty(), ErrorType.PROTOCOL, ErrorTag.BAD_ELEMENT,
"Schema not found for %s", key);
final String value = findAndParsePercentEncoded(nextIdentifierFromNextSequence(IDENTIFIER_PREDICATE));
schemaNode);
}
decoded = RestCodec.from(typedef, null, schemaContext).deserialize(value);
- if (decoded == null) {
- if (baseType instanceof IdentityrefTypeDefinition) {
- decoded = toQName(value, schemaNode, schemaContext);
- }
+ if (decoded == null && typedef instanceof IdentityrefTypeDefinition) {
+ decoded = toIdentityrefQName(value, schemaNode);
}
return decoded;
}
private void validArg() {
// every identifier except of the first MUST start with slash
if (offset != 0) {
- checkValid(SLASH == currentChar(), ErrorTag.MALFORMED_MESSAGE, "Identifier must start with '/'.");
+ checkValid('/' == currentChar(), ErrorTag.MALFORMED_MESSAGE, "Identifier must start with '/'.");
// skip consecutive slashes, users often assume restconf URLs behave just as HTTP does by squashing
// multiple slashes into a single one
- while (!allCharsConsumed() && SLASH == currentChar()) {
+ while (!allCharsConsumed() && '/' == currentChar()) {
skipCurrentChar();
}
private QName getQNameOfDataSchemaNode(final String nodeName) {
final DataSchemaNode dataSchemaNode = current.getDataSchemaNode();
- if (dataSchemaNode instanceof ContainerSchemaNode) {
- return getQNameOfDataSchemaNode((ContainerSchemaNode) dataSchemaNode, nodeName);
+ if (dataSchemaNode instanceof ContainerLike) {
+ return getQNameOfDataSchemaNode((ContainerLike) dataSchemaNode, nodeName);
} else if (dataSchemaNode instanceof ListSchemaNode) {
return getQNameOfDataSchemaNode((ListSchemaNode) dataSchemaNode, nodeName);
}
return parsedPrefix.toString();
}
- private static Object toQName(final String value, final DataSchemaNode schemaNode,
- final SchemaContext schemaContext) {
+ private QName toIdentityrefQName(final String value, final DataSchemaNode schemaNode) {
final String moduleName = toModuleName(value);
final String nodeName = toNodeName(value);
- final Module module = schemaContext.findModules(moduleName).iterator().next();
- for (final IdentitySchemaNode identitySchemaNode : module.getIdentities()) {
+ final Iterator<? extends Module> modulesIterator = schemaContext.findModules(moduleName).iterator();
+ if (!modulesIterator.hasNext()) {
+ throw new RestconfDocumentedException(String.format("Cannot decode value '%s' for identityref type "
+ + "in %s. Make sure reserved characters such as comma, single-quote, double-quote, colon,"
+ + " double-quote, space, and forward slash (,'\":\" /) are percent-encoded,"
+ + " for example ':' is '%%3A'", value, current.getIdentifier().getNodeType()),
+ ErrorType.PROTOCOL, ErrorTag.BAD_ELEMENT);
+ }
+ for (final IdentitySchemaNode identitySchemaNode : modulesIterator.next().getIdentities()) {
final QName qName = identitySchemaNode.getQName();
if (qName.getLocalName().equals(nodeName)) {
return qName;