*/
package org.opendaylight.yangtools.yang.parser.rfc7950.stmt.unique;
+import com.google.common.base.CharMatcher;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableSet;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
+import java.util.regex.Pattern;
import org.opendaylight.yangtools.yang.model.api.YangStmtMapping;
import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.SchemaNodeIdentifier;
import org.opendaylight.yangtools.yang.parser.spi.meta.SubstatementValidator;
import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
-public final class UniqueStatementSupport
- extends AbstractStatementSupport<Collection<SchemaNodeIdentifier.Relative>, UniqueStatement,
- EffectiveStatement<Collection<SchemaNodeIdentifier.Relative>, UniqueStatement>> {
- private static final Splitter SPACE_SPLITTER = Splitter.on(' ').omitEmptyStrings().trimResults();
+public final class UniqueStatementSupport extends AbstractStatementSupport<Collection<Relative>, UniqueStatement,
+ EffectiveStatement<Collection<Relative>, UniqueStatement>> {
+ /**
+ * Support 'sep' ABNF rule in RFC7950 section 14. CRLF pattern is used to squash line-break from CRLF to LF form
+ * and then we use SEP_SPLITTER, which can operate on single characters.
+ */
+ private static final Pattern CRLF_PATTERN = Pattern.compile("\r\n", Pattern.LITERAL);
+ private static final Splitter SEP_SPLITTER = Splitter.on(CharMatcher.anyOf(" \t\n").precomputed())
+ .omitEmptyStrings();
+
private static final SubstatementValidator SUBSTATEMENT_VALIDATOR = SubstatementValidator.builder(
YangStmtMapping.UNIQUE)
.build();
}
@Override
- public Collection<SchemaNodeIdentifier.Relative> parseArgumentValue(final StmtContext<?, ?, ?> ctx,
- final String value) {
+ public Collection<Relative> parseArgumentValue(final StmtContext<?, ?, ?> ctx, final String value) {
final Collection<Relative> uniqueConstraints = parseUniqueConstraintArgument(ctx, value);
SourceException.throwIf(uniqueConstraints.isEmpty(), ctx.getStatementSourceReference(),
"Invalid argument value '%s' of unique statement. The value must contains at least "
@Override
public EffectiveStatement<Collection<Relative>, UniqueStatement> createEffective(
- final StmtContext<Collection<Relative>, UniqueStatement,
- EffectiveStatement<Collection<Relative>, UniqueStatement>> ctx) {
+ final StmtContext<Collection<Relative>, UniqueStatement, EffectiveStatement<Collection<Relative>,
+ UniqueStatement>> ctx) {
return new UniqueEffectiveStatementImpl(ctx);
}
return SUBSTATEMENT_VALIDATOR;
}
- private static Collection<SchemaNodeIdentifier.Relative> parseUniqueConstraintArgument(
- final StmtContext<?, ?, ?> ctx, final String argumentValue) {
- final Set<SchemaNodeIdentifier.Relative> uniqueConstraintNodes = new HashSet<>();
- for (final String uniqueArgToken : SPACE_SPLITTER.split(argumentValue)) {
+ private static Collection<Relative> parseUniqueConstraintArgument(final StmtContext<?, ?, ?> ctx,
+ final String argumentValue) {
+ // deal with 'line-break' rule, which is either "\n" or "\r\n", but not "\r"
+ final String nocrlf = CRLF_PATTERN.matcher(argumentValue).replaceAll("\n");
+
+ final Set<Relative> uniqueConstraintNodes = new HashSet<>();
+ for (final String uniqueArgToken : SEP_SPLITTER.split(nocrlf)) {
final SchemaNodeIdentifier nodeIdentifier = ArgumentUtils.nodeIdentifierFromPath(ctx, uniqueArgToken);
SourceException.throwIf(nodeIdentifier.isAbsolute(), ctx.getStatementSourceReference(),
"Unique statement argument '%s' contains schema node identifier '%s' "
+ "which is not in the descendant node identifier form.", argumentValue, uniqueArgToken);
- uniqueConstraintNodes.add((SchemaNodeIdentifier.Relative) nodeIdentifier);
+ uniqueConstraintNodes.add((Relative) nodeIdentifier);
}
return ImmutableSet.copyOf(uniqueConstraintNodes);
}
--- /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.stmt;
+
+import static org.junit.Assert.assertNotNull;
+
+import org.junit.Test;
+import org.opendaylight.yangtools.yang.parser.spi.meta.SomeModifiersUnresolvedException;
+
+public class YT893Test {
+ @Test(expected = SomeModifiersUnresolvedException.class)
+ public void testCR() throws Exception {
+ StmtTestUtils.parseYangSource("/bugs/YT893/cr.yang");
+ }
+
+ @Test
+ public void testCRLF() throws Exception {
+ assertNotNull(StmtTestUtils.parseYangSource("/bugs/YT893/crlf.yang"));
+ }
+
+ @Test
+ public void testHTAB() throws Exception {
+ assertNotNull(StmtTestUtils.parseYangSource("/bugs/YT893/ht.yang"));
+ }
+
+ @Test
+ public void testLF() throws Exception {
+ assertNotNull(StmtTestUtils.parseYangSource("/bugs/YT893/lf.yang"));
+ }
+}