return transformEffective();
}
+ private SomeModifiersUnresolvedException propagateException(final SourceSpecificContext source,
+ final RuntimeException cause) throws SomeModifiersUnresolvedException {
+ final SourceIdentifier sourceId = Utils.createSourceIdentifier(source.getRoot());
+ if (!(cause instanceof SourceException)) {
+ /*
+ * This should not be happening as all our processing should provide SourceExceptions.
+ * We will wrap the exception to provide enough information to identify the problematic model,
+ * but also emit a warning so the offending codepath will get fixed.
+ */
+ LOG.warn("Unexpected error processing source {}. Please file an issue with this model attached.",
+ sourceId, cause);
+ }
+
+ throw new SomeModifiersUnresolvedException(currentPhase, sourceId, cause);
+ }
+
private EffectiveSchemaContext transformEffective() throws ReactorException {
Preconditions.checkState(finishedPhase == ModelProcessingPhase.EFFECTIVE_MODEL);
final List<DeclaredStatement<?>> rootStatements = new ArrayList<>(sources.size());
final List<EffectiveStatement<?, ?>> rootEffectiveStatements = new ArrayList<>(sources.size());
- SourceIdentifier sourceId = null;
try {
for (final SourceSpecificContext source : sources) {
final RootStatementContext<?, ?, ?> root = source.getRoot();
- sourceId = Utils.createSourceIdentifier(root);
- rootStatements.add(root.buildDeclared());
- rootEffectiveStatements.add(root.buildEffective());
+ try {
+ rootStatements.add(root.buildDeclared());
+ rootEffectiveStatements.add(root.buildEffective());
+ } catch (final RuntimeException ex) {
+ throw propagateException(source, ex);
+ }
}
- } catch (final SourceException ex) {
- throw new SomeModifiersUnresolvedException(currentPhase, sourceId, ex);
} finally {
RecursiveObjectLeaker.cleanup();
}
for (final SourceSpecificContext source : sources) {
try {
source.loadStatements();
- } catch (final SourceException ex) {
- final SourceIdentifier sourceId = Utils.createSourceIdentifier(source.getRoot());
- throw new SomeModifiersUnresolvedException(currentPhase, sourceId, ex);
+ } catch (final RuntimeException ex) {
+ throw propagateException(source, ex);
}
}
}
private void completePhaseActions() throws ReactorException {
Preconditions.checkState(currentPhase != null);
final List<SourceSpecificContext> sourcesToProgress = Lists.newArrayList(sources);
- SourceIdentifier sourceId = null;
- try {
- boolean progressing = true;
- while (progressing) {
- // We reset progressing to false.
- progressing = false;
- final Iterator<SourceSpecificContext> currentSource = sourcesToProgress.iterator();
- while (currentSource.hasNext()) {
- final SourceSpecificContext nextSourceCtx = currentSource.next();
- sourceId = Utils.createSourceIdentifier(nextSourceCtx.getRoot());
+ boolean progressing = true;
+ while (progressing) {
+ // We reset progressing to false.
+ progressing = false;
+ final Iterator<SourceSpecificContext> currentSource = sourcesToProgress.iterator();
+ while (currentSource.hasNext()) {
+ final SourceSpecificContext nextSourceCtx = currentSource.next();
+ try {
final PhaseCompletionProgress sourceProgress = nextSourceCtx.tryToCompletePhase(currentPhase);
switch (sourceProgress) {
- case FINISHED:
- currentSource.remove();
- // Fallback to progress, since we were able to make
- // progress in computation
- case PROGRESS:
- progressing = true;
- break;
- case NO_PROGRESS:
- // Noop
- break;
- default:
- throw new IllegalStateException("Unsupported phase progress " + sourceProgress);
+ case FINISHED:
+ currentSource.remove();
+ // Fallback to progress, since we were able to make
+ // progress in computation
+ case PROGRESS:
+ progressing = true;
+ break;
+ case NO_PROGRESS:
+ // Noop
+ break;
+ default:
+ throw new IllegalStateException("Unsupported phase progress " + sourceProgress);
}
+ } catch (RuntimeException ex) {
+ throw propagateException(nextSourceCtx, ex);
}
}
- } catch (final SourceException e) {
- throw new SomeModifiersUnresolvedException(currentPhase, sourceId, e);
}
if (!sourcesToProgress.isEmpty()) {
final SomeModifiersUnresolvedException buildFailure = addSourceExceptions(sourcesToProgress);
*/
package org.opendaylight.yangtools.yang.parser.stmt.rfc6020;
-import com.google.common.base.Preconditions;
import com.google.common.base.Verify;
import com.google.common.collect.ImmutableList.Builder;
import com.google.common.collect.ImmutableSet;
@Override
public SchemaNodeIdentifier parseArgumentValue(final StmtContext<?, ?, ?> ctx, final String value) {
- Preconditions.checkArgument(!PATH_REL_PATTERN1.matcher(value).matches()
- && !PATH_REL_PATTERN2.matcher(value).matches(),
- "An argument for augment can be only absolute path; or descendant if used in uses");
+ SourceException.throwIf(PATH_REL_PATTERN1.matcher(value).matches()
+ || PATH_REL_PATTERN2.matcher(value).matches(), ctx.getStatementSourceReference(),
+ "Augment argument \'%s\' is not valid, it can be only absolute path; or descendant if used in uses",
+ value);
return Utils.nodeIdentifierFromPath(ctx, value);
}
import org.opendaylight.yangtools.yang.parser.spi.source.ImportedModuleContext;
import org.opendaylight.yangtools.yang.parser.spi.source.ModuleCtxToModuleIdentifier;
import org.opendaylight.yangtools.yang.parser.spi.source.ModuleNameToNamespace;
+import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.ImportEffectiveStatementImpl;
public class ImportStatementDefinition extends
final URI importedModuleNamespace = importedModuleContext.getFromNamespace(ModuleNameToNamespace.class,
moduleName);
Verify.verifyNotNull(importedModuleNamespace);
- final String impPrefix = firstAttributeOf(stmt.declaredSubstatements(), PrefixStatement.class);
- Verify.verifyNotNull(impPrefix);
+ final String impPrefix = SourceException.throwIfNull(
+ firstAttributeOf(stmt.declaredSubstatements(), PrefixStatement.class),
+ stmt.getStatementSourceReference(), "Missing prefix statement");
+
stmt.addToNs(ImpPrefixToNamespace.class, impPrefix, importedModuleNamespace);
}
*/
package org.opendaylight.yangtools.yang.parser.stmt.rfc6020;
-import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSet.Builder;
import java.util.Collection;
import org.opendaylight.yangtools.yang.parser.spi.meta.AbstractStatementSupport;
import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContextUtils;
+import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.KeyEffectiveStatementImpl;
public class KeyStatementImpl extends AbstractDeclaredStatement<Collection<SchemaNodeIdentifier>> implements
// Throws NPE on nulls, retains first inserted value, cannot be modified
final Collection<SchemaNodeIdentifier> ret = builder.build();
-
- Preconditions.checkArgument(ret.size() == tokens, "Key argument '%s' contains duplicates. At %s", value,
- ctx.getStatementSourceReference());
+ SourceException.throwIf(ret.size() != tokens, ctx.getStatementSourceReference(),
+ "Key argument '%s' contains duplicates", value);
return ret;
}
}
@Override
- public void onFullDefinitionDeclared(StmtContext.Mutable<Collection<SchemaNodeIdentifier>, KeyStatement,
+ public void onFullDefinitionDeclared(final StmtContext.Mutable<Collection<SchemaNodeIdentifier>, KeyStatement,
EffectiveStatement<Collection<SchemaNodeIdentifier>, KeyStatement>> stmt) {
super.onFullDefinitionDeclared(stmt);
SUBSTATEMENT_VALIDATOR.validate(stmt);
import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
import org.opendaylight.yangtools.yang.model.util.RevisionAwareXPathImpl;
import org.opendaylight.yangtools.yang.parser.spi.meta.CopyType;
+import org.opendaylight.yangtools.yang.parser.spi.meta.InferenceException;
import org.opendaylight.yangtools.yang.parser.spi.meta.QNameCacheNamespace;
import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContextUtils;
try {
final QName qName = Utils.qNameFromArgument(ctx, nodeName);
qNames.add(qName);
- } catch (final Exception e) {
- throw new IllegalArgumentException(
- String.format("Failed to parse node '%s' in path '%s'", nodeName, path), e);
+ } catch (final RuntimeException e) {
+ throw new SourceException(ctx.getStatementSourceReference(), e,
+ "Failed to parse node '%s' in path '%s'", nodeName, path);
}
}
break;
}
- Preconditions.checkArgument(qNameModule != null,
- "Error in module '%s': can not resolve QNameModule for '%s'. Statement source at %s",
- ctx.getRoot().rawStatementArgument(), value, ctx.getStatementSourceReference());
+ qNameModule = InferenceException.throwIfNull(qNameModule, ctx.getStatementSourceReference(),
+ "Cannot resolve QNameModule for '%s'", value);
+
final QNameModule resultQNameModule;
if (qNameModule.getRevision() == null) {
resultQNameModule = QNameModule.create(qNameModule.getNamespace(), SimpleDateFormatUtil.DEFAULT_DATE_REV)
}
public static DeviateKind parseDeviateFromString(final StmtContext<?, ?, ?> ctx, final String deviateKeyword) {
- return Preconditions.checkNotNull(KEYWORD_TO_DEVIATE_MAP.get(deviateKeyword),
- "String '%s' is not valid deviate argument. Statement source at %s", deviateKeyword,
- ctx.getStatementSourceReference());
+ return SourceException.throwIfNull(KEYWORD_TO_DEVIATE_MAP.get(deviateKeyword),
+ ctx.getStatementSourceReference(), "String '%s' is not valid deviate argument", deviateKeyword);
}
public static Status parseStatus(final String value) {
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import org.junit.Ignore;
"/semantic-statement-parser/augment-arg-parsing/root-invalid-xpath.yang", false);
@Test
- public void validAugAbsTest() throws SourceException, ReactorException {
+ public void validAugAbsTest() throws ReactorException {
BuildAction reactor = YangInferencePipeline.RFC6020_REACTOR.newBuild();
addSources(reactor, IMPORTED, VALID_ARGS);
}
@Test
- public void invalidAugRel1Test() throws SourceException, ReactorException {
+ public void invalidAugRel1Test() {
BuildAction reactor = YangInferencePipeline.RFC6020_REACTOR.newBuild();
addSources(reactor, INVALID_REL1);
try {
reactor.build();
fail("reactor.process should fail due to invalid relative path");
- } catch (Exception e) {
- assertEquals(IllegalArgumentException.class, e.getClass());
+ } catch (ReactorException e) {
+ assertSourceExceptionCause(e, "Augment argument './aug1/aug11' is not valid");
}
}
@Test
- public void invalidAugRel2Test() throws SourceException, ReactorException {
+ public void invalidAugRel2Test() {
BuildAction reactor = YangInferencePipeline.RFC6020_REACTOR.newBuild();
addSources(reactor, INVALID_REL2);
try {
reactor.build();
fail("reactor.process should fail due to invalid relative path");
- } catch (Exception e) {
- assertEquals(IllegalArgumentException.class, e.getClass());
+ } catch (ReactorException e) {
+ assertSourceExceptionCause(e, "Augment argument '../aug1/aug11' is not valid");
}
}
@Test
- public void invalidAugAbs() throws SourceException, ReactorException {
+ public void invalidAugAbs() {
BuildAction reactor = YangInferencePipeline.RFC6020_REACTOR.newBuild();
addSources(reactor, INVALID_ABS);
try {
reactor.build();
fail("reactor.process should fail due to invalid absolute path");
- } catch (Exception e) {
- assertEquals(IllegalArgumentException.class, e.getClass());
+ } catch (ReactorException e) {
+ assertSourceExceptionCause(e, "Augment argument '//aug1/aug11/aug111' is not valid");
}
}
@Test
- public void invalidAugAbsPrefixedNoImp() throws SourceException, ReactorException {
+ public void invalidAugAbsPrefixedNoImp() {
BuildAction reactor = YangInferencePipeline.RFC6020_REACTOR.newBuild();
addSources(reactor, INVALID_ABS_PREFIXED_NO_IMP);
try {
reactor.build();
fail("reactor.process should fail due to missing import from augment path");
- } catch (Exception e) {
- assertEquals(IllegalArgumentException.class, e.getClass());
+ } catch (ReactorException e) {
+ assertSourceExceptionCause(e, "Failed to parse node 'imp:aug1'");
}
}
}
}
+ private static void assertSourceExceptionCause(final Throwable e, final String start) {
+ final Throwable cause = e.getCause();
+ assertTrue(cause instanceof SourceException);
+ assertTrue(cause.getMessage().startsWith(start));
+ }
+
private static void addSources(final BuildAction reactor, final YangStatementSourceImpl... sources) {
for (YangStatementSourceImpl source : sources) {
reactor.addSource(source);
public class Bug4933Test {
@Test
- public void test() throws SourceException, ReactorException, FileNotFoundException, URISyntaxException {
+ public void test() throws ReactorException, FileNotFoundException, URISyntaxException {
SchemaContext context = StmtTestUtils.parseYangSources("/bugs/bug4933/correct");
assertNotNull(context);
}
@Test
- public void incorrectKeywordTest() throws SourceException, ReactorException, FileNotFoundException,
- URISyntaxException {
+ public void incorrectKeywordTest() throws FileNotFoundException, URISyntaxException {
try {
StmtTestUtils.parseYangSources("/bugs/bug4933/incorrect");
- fail("NullPointerException should be thrown.");
- } catch (NullPointerException e) {
- assertTrue(e.getMessage().startsWith("String 'not_supported' is not valid deviate argument. Statement source at"));
+ fail("ReactorException should be thrown.");
+ } catch (ReactorException e) {
+ final Throwable cause = e.getCause();
+ assertTrue(cause instanceof SourceException);
+ assertTrue(cause.getMessage().startsWith("String 'not_supported' is not valid deviate argument"));
}
}
}
package org.opendaylight.yangtools.yang.stmt;
-import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+
import org.junit.Test;
import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
"/semantic-statement-parser/key-arg-parsing/key-comp-duplicate.yang", false);
@Test
- public void keySimpleTest() throws SourceException, ReactorException {
+ public void keySimpleTest() throws ReactorException {
BuildAction reactor = YangInferencePipeline.RFC6020_REACTOR.newBuild();
addSources(reactor, KEY_SIMPLE_AND_COMP);
}
@Test
- public void keyCompositeInvalid() throws SourceException, ReactorException {
+ public void keyCompositeInvalid() {
BuildAction reactor = YangInferencePipeline.RFC6020_REACTOR.newBuild();
addSources(reactor, KEY_COMP_DUPLICATE);
try {
reactor.build();
fail("reactor.process should fail due to duplicate name in key");
- } catch (Exception e) {
- assertEquals(IllegalArgumentException.class, e.getClass());
+ } catch (ReactorException e) {
+ final Throwable cause = e.getCause();
+ assertTrue(cause instanceof SourceException);
+ assertTrue(cause.getMessage().startsWith("Key argument 'key1 key2 key2' contains duplicates"));
}
}
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
-import com.google.common.base.VerifyException;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
@Test
public void missingElementException() throws URISyntaxException, ReactorException {
- expectedEx.expect(VerifyException.class);
+ expectedEx.expect(SomeModifiersUnresolvedException.class);
TestUtils.loadModules(getClass().getResource("/substatement-validator/missing-element").toURI());
}
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
import java.net.URISyntaxException;
import java.util.Set;
}
// parsing yin file with duplicate key name in a list statement
- @Test(expected = IllegalArgumentException.class)
- public void readAndParseInvalidYinFileTest2() throws ReactorException {
+ public void readAndParseInvalidYinFileTest2() {
CrossSourceStatementReactor.BuildAction reactor = YangInferencePipeline.RFC6020_REACTOR.newBuild();
addSources(reactor, INVALID_YIN_FILE_2);
- EffectiveSchemaContext result = reactor.buildEffective();
- assertNotNull(result);
+
+ try {
+ reactor.buildEffective();
+ fail("Reactor exception should have been thrown");
+ } catch (ReactorException e) {
+ final Throwable cause = e.getCause();
+ assertTrue(cause instanceof SourceException);
+ assertTrue(cause.getMessage().startsWith(
+ "Key argument 'testing-string testing-string' contains duplicates"));
+ }
}
@Test