package org.opendaylight.yangtools.yang.common;
import static org.opendaylight.yangtools.yang.common.SimpleDateFormatUtil.getRevisionFormat;
+
import com.google.common.base.Preconditions;
import com.google.common.collect.Interner;
import com.google.common.collect.Interners;
import static org.hamcrest.CoreMatchers.containsString;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
+
import com.google.common.base.Joiner;
import java.io.File;
import java.io.FileInputStream;
assertVerificationException(
e,
"org.opendaylight.yangtools.yang.parser.spi.meta.InferenceException: Imported module " +
- "[ModuleIdentifierImpl{name='unknownDep', namespace=null, revision=2013-02-27}");
+ "[unknownDep] was not found.");
return;
}
--- /dev/null
+/*
+ * Copyright (c) 2016 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.parser.spi;
+
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.ModuleStatement;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StatementNamespace;
+
+/**
+ * pre-linkage namespace class for storing modules into Yang model storage keyed by module names
+ */
+public interface PreLinkageModuleNamespace extends
+ StatementNamespace<String, ModuleStatement, EffectiveStatement<String, ModuleStatement>> {
+}
// NOOP for most implementations
}
+ /**
+ *
+ * {@inheritDoc}
+ *
+ * Subclasses of this class may override this method to perform actions on
+ * this event or register modification action using
+ * {@link StmtContext.Mutable#newInferenceAction(ModelProcessingPhase)}.
+ *
+ */
+ @Override
+ public void onPreLinkageDeclared(StmtContext.Mutable<A, D, E> stmt) {
+ // NOOP for most implementations
+ }
+
/**
*
* {@inheritDoc}
import javax.annotation.Nullable;
public enum ModelProcessingPhase {
+ INIT(null),
+ /**
+ *
+ * Preliminary cross-source relationship resolution phase which collects
+ * available module names and module namespaces. It is necessary in order to
+ * correct resolution of unknown statements used in linkage phase (e.g.
+ * semantic version of yang modules).
+ */
+ SOURCE_PRE_LINKAGE(INIT),
/**
*
* Cross-source relationship resolution phase.
* <p>
- * In this phase of processing only statements which affects
- * cross-source relationship (e.g. imports / includes)
- * are processed.
+ * In this phase of processing only statements which affects cross-source
+ * relationship (e.g. imports / includes) are processed.
* <p>
- * At end of this phase all source related contexts should
- * be bind to their imports and includes to allow
- * visibility of custom defined statements in following
- * phases.
+ * At end of this phase all source related contexts should be bind to their
+ * imports and includes to allow visibility of custom defined statements in
+ * following phases.
*/
- INIT(null),
- SOURCE_LINKAGE(INIT),
+ SOURCE_LINKAGE(SOURCE_PRE_LINKAGE),
STATEMENT_DEFINITION(SOURCE_LINKAGE),
FULL_DECLARATION(STATEMENT_DEFINITION),
EFFECTIVE_MODEL(FULL_DECLARATION);
* @param <E>
* Effective Statement representation
*/
-public interface StatementSupport<A, D extends DeclaredStatement<A>, E extends EffectiveStatement<A, D>> extends StatementDefinition, StatementFactory<A, D, E> {
+public interface StatementSupport<A, D extends DeclaredStatement<A>, E extends EffectiveStatement<A, D>> extends
+ StatementDefinition, StatementFactory<A, D, E> {
/**
- * Returns public statement definition, which will be present in builded statements.
+ * Returns public statement definition, which will be present in builded
+ * statements.
*
- * Public statement definition may be used to provide different implementation
- * of statement definition, which will not retain any build specific data
- * or context.
+ * Public statement definition may be used to provide different
+ * implementation of statement definition, which will not retain any build
+ * specific data or context.
*
- * @return public statement definition, which will be present in builded statements.
+ * @return public statement definition, which will be present in builded
+ * statements.
*/
- StatementDefinition getPublicView();
+ StatementDefinition getPublicView();
/**
*
* Parses textual representation of argument in object representation.
*
- * @param ctx Context, which may be used to access source-specific namespaces
- * required for parsing.
- * @param value String representation of value, as was present in text source.
+ * @param ctx
+ * Context, which may be used to access source-specific
+ * namespaces required for parsing.
+ * @param value
+ * String representation of value, as was present in text source.
* @return Parsed value
*/
- A parseArgumentValue(StmtContext<?, ?, ?> ctx, String value) throws SourceException;
+ A parseArgumentValue(StmtContext<?, ?, ?> ctx, String value) throws SourceException;
/**
*
* @param stmt
* Context of added statement. No substatement are available.
*/
- void onStatementAdded(StmtContext.Mutable<A, D, E> stmt);
+ void onStatementAdded(StmtContext.Mutable<A, D, E> stmt);
/**
*
* Invoked when statement is closed during
- * {@link ModelProcessingPhase#STATEMENT_DEFINITION} phase.
+ * {@link ModelProcessingPhase#SOURCE_PRE_LINKAGE} phase, only substatements
+ * from this and previous phase are available.
+ *
+ * Implementation may use method to perform actions on this event or
+ * register modification action using
+ * {@link StmtContext.Mutable#newInferenceAction(ModelProcessingPhase)}.
+ *
+ * @param stmt
+ * Context of added statement.
+ */
+ void onPreLinkageDeclared(StmtContext.Mutable<A, D, E> stmt);
+
+ /**
*
* Invoked when statement is closed during
- * {@link ModelProcessingPhase#STATEMENT_DEFINITION} phase, only substatements from
- * this and previous phase are available.
+ * {@link ModelProcessingPhase#SOURCE_LINKAGE} phase, only substatements
+ * from this and previous phase are available.
*
* Implementation may use method to perform actions on this event or
* register modification action using
* @param stmt
* Context of added statement.
*/
- void onLinkageDeclared(StmtContext.Mutable<A, D, E> stmt) throws SourceException;
+ void onLinkageDeclared(StmtContext.Mutable<A, D, E> stmt) throws SourceException;
/**
*
* {@link ModelProcessingPhase#STATEMENT_DEFINITION} phase.
*
* Invoked when statement is closed during
- * {@link ModelProcessingPhase#STATEMENT_DEFINITION} phase, only substatements from
- * this phase are available.
+ * {@link ModelProcessingPhase#STATEMENT_DEFINITION} phase, only
+ * substatements from this phase are available.
*
* Implementation may use method to perform actions on this event or
* register modification action using
* Context of added statement. Argument and statement parent is
* accessible.
*/
- void onStatementDefinitionDeclared(StmtContext.Mutable<A, D, E> stmt) throws SourceException;
+ void onStatementDefinitionDeclared(StmtContext.Mutable<A, D, E> stmt) throws SourceException;
/**
*
* Context of added statement. Argument and statement parent is
* accessible.
*/
- void onFullDefinitionDeclared(StmtContext.Mutable<A, D, E> stmt) throws SourceException;
-
+ void onFullDefinitionDeclared(StmtContext.Mutable<A, D, E> stmt) throws SourceException;
}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2016 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.parser.spi.source;
+
+import java.net.URI;
+import org.opendaylight.yangtools.yang.model.api.meta.IdentifierNamespace;
+
+/**
+ *
+ * Pre-linkage source-specific mapping of prefixes to module namespaces
+ *
+ */
+public interface ImpPrefixToNamespace extends IdentifierNamespace<String, URI> {
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2016 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.parser.spi.source;
+
+import java.net.URI;
+import org.opendaylight.yangtools.yang.model.api.meta.IdentifierNamespace;
+
+/**
+ *
+ * Pre-linkage global mapping of module names to namespaces
+ *
+ */
+public interface ModuleNameToNamespace extends IdentifierNamespace<String, URI> {
+
+}
*/
package org.opendaylight.yangtools.yang.parser.spi.source;
+import java.net.URISyntaxException;
import javax.annotation.Nullable;
import org.opendaylight.yangtools.yang.common.QNameModule;
import org.opendaylight.yangtools.yang.model.api.meta.IdentifierNamespace;
* XML Namespace
* @return QNameModule associated with supplied namespace, or null if prefix
* is not defined.
+ * @throws URISyntaxException if the input string is not valid URI
*
*/
- @Nullable QNameModule getByNamespace(String namespace);
+ @Nullable QNameModule getByNamespace(String namespace) throws URISyntaxException;
+
+ /**
+ * Pre-linkage map does not consider revision-dates of modules and it contains module namespaces only.
+ *
+ * @return true if it is the pre-linkage map.
+ *
+ */
+ boolean isPreLinkageMap();
}
*/
package org.opendaylight.yangtools.yang.parser.spi.source;
-import org.opendaylight.yangtools.yang.common.QNameModule;
-
-import javax.annotation.Nullable;
+import java.net.URI;
+import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.Map;
+import javax.annotation.Nullable;
+import org.opendaylight.yangtools.yang.common.QNameModule;
public class PrefixToModuleMap implements PrefixToModule {
private Map<String, QNameModule> prefixToModuleMap = new HashMap<>();
+ private Map<URI, QNameModule> namespaceToModuleMap = new HashMap<>();
+ private final boolean preLinkageMap;
+
+ public PrefixToModuleMap() {
+ this(false);
+ }
+
+ public PrefixToModuleMap(boolean preLinkageMap) {
+ this.preLinkageMap = preLinkageMap;
+ }
public void put(String prefix, QNameModule qNameModule) {
prefixToModuleMap.put(prefix, qNameModule);
+ namespaceToModuleMap.put(qNameModule.getNamespace(), qNameModule);
}
@Nullable
@Nullable
@Override
- public QNameModule getByNamespace(String namespace) {
- return null;
+ public QNameModule getByNamespace(String namespace) throws URISyntaxException {
+ return namespaceToModuleMap.get(new URI(namespace));
+ }
+
+ @Override
+ public boolean isPreLinkageMap() {
+ return preLinkageMap;
}
}
*/
package org.opendaylight.yangtools.yang.parser.spi.source;
+import java.net.URI;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.model.api.meta.IdentifierNamespace;
import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
*/
public interface QNameToStatementDefinition extends IdentifierNamespace<QName, StatementDefinition> {
+ /**
+ * Returns StatementDefinition with specified QName.
+ *
+ * @param identifier
+ * QName of requested statement
+ * @return StatementDefinition
+ */
+ @Nullable
+ StatementDefinition get(@Nonnull QName identifier);
+
+ /**
+ * Returns StatementDefinition with specified namespace and localName.
+ *
+ * @param namespace
+ * namespace of requested statement
+ * @param localName
+ * localName of requested statement
+ * @return StatementDefinition
+ */
+ @Nullable
+ StatementDefinition getByNamespaceAndLocalName(@Nonnull final URI namespace, @Nonnull final String localName);
}
*/
package org.opendaylight.yangtools.yang.parser.spi.source;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
-
-import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
+import java.net.URI;
import java.util.HashMap;
import java.util.Map;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
public class QNameToStatementDefinitionMap implements QNameToStatementDefinition {
private Map<QName, StatementDefinition> qNameToStmtDefMap = new HashMap<>();
+ private Map<QName, StatementDefinition> qNameWithoutRevisionToStmtDefMap = new HashMap<>();
public void put(QName qName, StatementDefinition stDef) {
qNameToStmtDefMap.put(qName, stDef);
+ qNameWithoutRevisionToStmtDefMap.put(QName.create(qName.getNamespace(), null, qName.getLocalName()), stDef);
}
@Nullable
public StatementDefinition get(@Nonnull QName identifier) {
return qNameToStmtDefMap.get(identifier);
}
+
+ @Nullable
+ @Override
+ public StatementDefinition getByNamespaceAndLocalName(URI namespace, @Nonnull String localName) {
+ return qNameWithoutRevisionToStmtDefMap.get(QName.create(namespace, null, localName));
+ }
}
*/
package org.opendaylight.yangtools.yang.parser.spi.source;
+
/**
*
* Statement stream source, which is used for inference of effective model.
* Steps (in order of invocation) are:
*
* <ol>
- * <li>{@link #writeLinkage(StatementWriter, QNameToStatementDefinition)} -
+ * <li>{@link #writePreLinkage(StatementWriter, QNameToStatementDefinition)} -
+ * Source MUST emit only statements related in pre-linkage, which are present in
+ * supplied statement definition map. This step is used as preparatory cross-source
+ * relationship resolution phase which collects available module names and namespaces.
+ * It is necessary in order to correct resolution of unknown statements used by linkage
+ * phase (e.g. semantic version of yang modules).
+ * </li>
+ * <li>{@link #writeLinkage(StatementWriter, QNameToStatementDefinition, PrefixToModule)} -
* Source MUST emit only statements related in linkage, which are present in
* supplied statement definition map. This step is used to build cross-source
* linkage and visibility relationship, and to determine XMl namespaces and
*/
public interface StatementStreamSource {
+ /**
+ *
+ * Emits only pre-linkage-related statements to supplied {@code writer}.
+ *
+ * @param writer
+ * {@link StatementWriter} which should be used to emit
+ * statements.
+ * @param stmtDef
+ * Map of available statement definitions. Only these statements
+ * may be written to statement writer, source MUST ignore and MUST NOT
+ * emit any other statements.
+ *
+ * @throws SourceException
+ * If source was is not valid, or provided statement writer
+ * failed to write statements.
+ */
+ void writePreLinkage(StatementWriter writer, QNameToStatementDefinition stmtDef) throws SourceException;
+
/**
*
* Emits only linkage-related statements to supplied {@code writer}.
* Map of available statement definitions. Only these statements
* may be written to statement writer, source MUST ignore and MUST NOT
* emit any other statements.
+ * @param preLinkagePrefixes
+ * Pre-linkage map of source-specific prefixes to namespaces
*
* @throws SourceException
* If source was is not valid, or provided statement writer
* failed to write statements.
*/
- void writeLinkage(StatementWriter writer, QNameToStatementDefinition stmtDef) throws SourceException;
+ void writeLinkage(StatementWriter writer, QNameToStatementDefinition stmtDef, PrefixToModule preLinkagePrefixes) throws SourceException;
/**
*
package org.opendaylight.yangtools.yang.parser.spi.source;
import org.opendaylight.yangtools.yang.model.api.Rfc6020Mapping;
-
import org.opendaylight.yangtools.yang.model.api.meta.IdentifierNamespace;
/**
- *
- * Source-specific mapping of prefixes to namespaces
- *
+ * Map of statement order.
*/
public interface StmtOrderingNamespace extends
IdentifierNamespace<Rfc6020Mapping, Integer> {
-
-}
+}
\ No newline at end of file
private static final Logger LOG = LoggerFactory.getLogger(BuildGlobalContext.class);
private static final List<ModelProcessingPhase> PHASE_EXECUTION_ORDER = ImmutableList.<ModelProcessingPhase>builder()
+ .add(ModelProcessingPhase.SOURCE_PRE_LINKAGE)
.add(ModelProcessingPhase.SOURCE_LINKAGE)
.add(ModelProcessingPhase.STATEMENT_DEFINITION)
.add(ModelProcessingPhase.FULL_DECLARATION)
import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Multimap;
+import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
import org.opendaylight.yangtools.yang.parser.spi.source.BelongsToPrefixToModuleIdentifier;
import org.opendaylight.yangtools.yang.parser.spi.source.ImpPrefixToModuleIdentifier;
+import org.opendaylight.yangtools.yang.parser.spi.source.ImpPrefixToNamespace;
import org.opendaylight.yangtools.yang.parser.spi.source.ModuleIdentifierToModuleQName;
import org.opendaylight.yangtools.yang.parser.spi.source.PrefixToModule;
import org.opendaylight.yangtools.yang.parser.spi.source.PrefixToModuleMap;
void loadStatements() throws SourceException {
switch (inProgressPhase) {
+ case SOURCE_PRE_LINKAGE:
+ source.writePreLinkage(new StatementContextWriter(this, inProgressPhase), stmtDef());
+ break;
case SOURCE_LINKAGE:
- source.writeLinkage(new StatementContextWriter(this, inProgressPhase), stmtDef());
+ source.writeLinkage(new StatementContextWriter(this, inProgressPhase), stmtDef(), preLinkagePrefixes());
break;
case STATEMENT_DEFINITION:
source.writeLinkageAndStatementDefinitions(new StatementContextWriter(this, inProgressPhase), stmtDef(), prefixes());
}
}
+ private PrefixToModule preLinkagePrefixes() {
+ PrefixToModuleMap preLinkagePrefixes = new PrefixToModuleMap(true);
+ Map<String, URI> prefixToNamespaceMap = getAllFromLocalStorage(ImpPrefixToNamespace.class);
+ if(prefixToNamespaceMap == null) {
+ //:FIXME if it is a submodule without any import, the map is null. Handle also submodules and includes...
+ return null;
+ }
+ for (Entry<String, URI> prefixToNamespace : prefixToNamespaceMap.entrySet()) {
+ preLinkagePrefixes.put(prefixToNamespace.getKey(), QNameModule.create(prefixToNamespace.getValue(), null));
+ }
+
+ return preLinkagePrefixes;
+ }
+
private PrefixToModule prefixes() {
final Map<String, ModuleIdentifier> allPrefixes = getRoot().getAllFromNamespace(ImpPrefixToModuleIdentifier
.class);
public void onDeclarationFinished(Mutable<A,D,E> statement, ModelProcessingPhase phase) throws SourceException {
switch (phase) {
+ case SOURCE_PRE_LINKAGE:
+ support.onPreLinkageDeclared(statement);
+ break;
case SOURCE_LINKAGE:
support.onLinkageDeclared(statement);
break;
package org.opendaylight.yangtools.yang.parser.stmt.rfc6020;
import static org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase.SOURCE_LINKAGE;
+import static org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase.SOURCE_PRE_LINKAGE;
import static org.opendaylight.yangtools.yang.parser.spi.meta.StmtContextUtils.firstAttributeOf;
+
import com.google.common.base.Optional;
+import com.google.common.base.Verify;
import java.net.URI;
import java.util.Collection;
import java.util.Date;
import org.opendaylight.yangtools.yang.model.api.stmt.RevisionDateStatement;
import org.opendaylight.yangtools.yang.parser.builder.impl.ModuleIdentifierImpl;
import org.opendaylight.yangtools.yang.parser.spi.ModuleNamespace;
+import org.opendaylight.yangtools.yang.parser.spi.PreLinkageModuleNamespace;
import org.opendaylight.yangtools.yang.parser.spi.SubstatementValidator;
import org.opendaylight.yangtools.yang.parser.spi.meta.AbstractStatementSupport;
import org.opendaylight.yangtools.yang.parser.spi.meta.InferenceException;
import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext.Mutable;
import org.opendaylight.yangtools.yang.parser.spi.source.ImpPrefixToModuleIdentifier;
+import org.opendaylight.yangtools.yang.parser.spi.source.ImpPrefixToNamespace;
+import org.opendaylight.yangtools.yang.parser.spi.source.ModuleNameToNamespace;
import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.ImportEffectiveStatementImpl;
public class ImportStatementDefinition
SUBSTATEMENT_VALIDATOR.validate(stmt);
}
+ @Override
+ public void onPreLinkageDeclared(Mutable<String, ImportStatement, EffectiveStatement<String, ImportStatement>> stmt) {
+ final String moduleName = stmt.getStatementArgument();
+ final ModelActionBuilder importAction = stmt.newInferenceAction(SOURCE_PRE_LINKAGE);
+ final Prerequisite<StmtContext<?, ?, ?>> imported = importAction.requiresCtx(stmt,
+ PreLinkageModuleNamespace.class, moduleName, SOURCE_PRE_LINKAGE);
+ final Prerequisite<Mutable<?, ?, ?>> linkageTarget = importAction
+ .mutatesCtx(stmt.getRoot(), SOURCE_PRE_LINKAGE);
+
+ importAction.apply(new InferenceAction() {
+ @Override
+ public void apply() {
+ StmtContext<?, ?, ?> importedModuleContext = imported.get();
+ Verify.verify(moduleName.equals(importedModuleContext.getStatementArgument()));
+ final URI importedModuleNamespace = importedModuleContext.getFromNamespace(ModuleNameToNamespace.class,
+ moduleName);
+ Verify.verifyNotNull(importedModuleNamespace);
+ final String impPrefix = firstAttributeOf(stmt.declaredSubstatements(), PrefixStatement.class);
+ Verify.verifyNotNull(impPrefix);
+ stmt.addToNs(ImpPrefixToNamespace.class, impPrefix, importedModuleNamespace);
+ }
+
+ @Override
+ public void prerequisiteFailed(final Collection<? extends Prerequisite<?>> failed) {
+ InferenceException.throwIf(failed.contains(imported), stmt.getStatementSourceReference(),
+ "Imported module [%s] was not found.", moduleName);
+ }
+ });
+ }
+
@Override
public void onLinkageDeclared(
final Mutable<String, ImportStatement, EffectiveStatement<String, ImportStatement>> stmt) {
import static org.opendaylight.yangtools.yang.parser.spi.SubstatementValidator.MAX;
import static org.opendaylight.yangtools.yang.parser.spi.meta.StmtContextUtils.firstAttributeOf;
+
import com.google.common.base.Optional;
import java.net.URI;
import java.util.Date;
import org.opendaylight.yangtools.yang.parser.builder.impl.ModuleIdentifierImpl;
import org.opendaylight.yangtools.yang.parser.spi.ModuleNamespace;
import org.opendaylight.yangtools.yang.parser.spi.NamespaceToModule;
+import org.opendaylight.yangtools.yang.parser.spi.PreLinkageModuleNamespace;
import org.opendaylight.yangtools.yang.parser.spi.SubstatementValidator;
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.StmtContext.Mutable;
import org.opendaylight.yangtools.yang.parser.spi.source.ImpPrefixToModuleIdentifier;
+import org.opendaylight.yangtools.yang.parser.spi.source.ImpPrefixToNamespace;
import org.opendaylight.yangtools.yang.parser.spi.source.ModuleCtxToModuleQName;
import org.opendaylight.yangtools.yang.parser.spi.source.ModuleIdentifierToModuleQName;
import org.opendaylight.yangtools.yang.parser.spi.source.ModuleNameToModuleQName;
+import org.opendaylight.yangtools.yang.parser.spi.source.ModuleNameToNamespace;
import org.opendaylight.yangtools.yang.parser.spi.source.ModuleNamespaceForBelongsTo;
import org.opendaylight.yangtools.yang.parser.spi.source.ModuleQNameToModuleName;
import org.opendaylight.yangtools.yang.parser.spi.source.PrefixToModule;
return new ModuleEffectiveStatementImpl(ctx);
}
+ @Override
+ public void onPreLinkageDeclared(Mutable<String, ModuleStatement, EffectiveStatement<String, ModuleStatement>> stmt) {
+ final String moduleName = stmt.getStatementArgument();
+
+ final URI moduleNs = firstAttributeOf(stmt.declaredSubstatements(),
+ NamespaceStatement.class);
+ SourceException.throwIfNull(moduleNs, stmt.getStatementSourceReference(),
+ "Namespace of the module [%s] is missing", stmt.getStatementArgument());
+ stmt.addToNs(ModuleNameToNamespace.class, moduleName, moduleNs);
+
+ final String modulePrefix = firstAttributeOf(stmt.declaredSubstatements(), PrefixStatement.class);
+ SourceException.throwIfNull(modulePrefix, stmt.getStatementSourceReference(),
+ "Prefix of the module [%s] is missing", stmt.getStatementArgument());
+ stmt.addToNs(ImpPrefixToNamespace.class, modulePrefix, moduleNs);
+
+ stmt.addContext(PreLinkageModuleNamespace.class, moduleName, stmt);
+ };
+
@Override
public void onLinkageDeclared(final Mutable<String, ModuleStatement, EffectiveStatement<String, ModuleStatement>> stmt) {
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import org.opendaylight.yangtools.yang.model.api.RevisionAwareXPath;
import org.opendaylight.yangtools.yang.model.api.Rfc6020Mapping;
import org.opendaylight.yangtools.yang.model.api.Status;
+import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
import org.opendaylight.yangtools.yang.model.api.stmt.BelongsToStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.ModuleStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.RevisionStatement;
* @return valid QName for declared statement to be written
*
*/
- public static QName getValidStatementDefinition(final PrefixToModule prefixes, final QNameToStatementDefinition
- stmtDef, final QName identifier) {
+ public static QName getValidStatementDefinition(final PrefixToModule prefixes,
+ final QNameToStatementDefinition stmtDef, final QName identifier) {
if (stmtDef.get(identifier) != null) {
return stmtDef.get(identifier).getStatementName();
} else {
if (namesParts.length == 2) {
String prefix = namesParts[0];
String localName = namesParts[1];
- if (prefixes != null && prefixes.get(prefix) != null
- && stmtDef.get(QName.create(prefixes.get(prefix), localName)) != null) {
- return QName.create(prefixes.get(prefix), localName);
+
+ if (prefixes == null) {
+ return null;
+ }
+
+ QNameModule qNameModule = prefixes.get(prefix);
+ if (qNameModule == null) {
+ return null;
+ }
+
+ if (prefixes.isPreLinkageMap()) {
+ StatementDefinition foundStmtDef = stmtDef.getByNamespaceAndLocalName(qNameModule.getNamespace(),
+ localName);
+ return foundStmtDef != null ? foundStmtDef.getStatementName() : null;
+ } else {
+ QName qName = QName.create(qNameModule, localName);
+ return stmtDef.get(qName) != null ? qName : null;
}
}
}
import org.opendaylight.yangtools.yang.parser.spi.IdentityNamespace;
import org.opendaylight.yangtools.yang.parser.spi.ModuleNamespace;
import org.opendaylight.yangtools.yang.parser.spi.NamespaceToModule;
+import org.opendaylight.yangtools.yang.parser.spi.PreLinkageModuleNamespace;
import org.opendaylight.yangtools.yang.parser.spi.SubmoduleNamespace;
import org.opendaylight.yangtools.yang.parser.spi.TypeNamespace;
import org.opendaylight.yangtools.yang.parser.spi.meta.DerivedIdentitiesNamespace;
import org.opendaylight.yangtools.yang.parser.spi.source.BelongsToPrefixToModuleIdentifier;
import org.opendaylight.yangtools.yang.parser.spi.source.BelongsToPrefixToModuleName;
import org.opendaylight.yangtools.yang.parser.spi.source.ImpPrefixToModuleIdentifier;
+import org.opendaylight.yangtools.yang.parser.spi.source.ImpPrefixToNamespace;
import org.opendaylight.yangtools.yang.parser.spi.source.IncludedSubmoduleNameToIdentifier;
import org.opendaylight.yangtools.yang.parser.spi.source.ModuleCtxToModuleQName;
import org.opendaylight.yangtools.yang.parser.spi.source.ModuleIdentifierToModuleQName;
import org.opendaylight.yangtools.yang.parser.spi.source.ModuleNameToModuleQName;
+import org.opendaylight.yangtools.yang.parser.spi.source.ModuleNameToNamespace;
import org.opendaylight.yangtools.yang.parser.spi.source.ModuleNamespaceForBelongsTo;
import org.opendaylight.yangtools.yang.parser.spi.source.ModuleQNameToModuleName;
import org.opendaylight.yangtools.yang.parser.spi.source.PrefixToModule;
.builder().addSupport(global(ValidationBundlesNamespace.class))
.build();
- public static final StatementSupportBundle LINKAGE_BUNDLE = StatementSupportBundle
+ public static final StatementSupportBundle PRE_LINKAGE_BUNDLE = StatementSupportBundle
.derivedFrom(INIT_BUNDLE)
.addSupport(new ModuleStatementSupport())
.addSupport(new SubmoduleStatementImpl.Definition())
.addSupport(new IncludeStatementImpl.Definition())
.addSupport(new PrefixStatementImpl.Definition())
.addSupport(new YangVersionStatementImpl.Definition())
+ .addSupport(global(ModuleNameToNamespace.class))
+ .addSupport(global(PreLinkageModuleNamespace.class))
+ .addSupport(sourceLocal(ImpPrefixToNamespace.class))
+ .build();
+
+ public static final StatementSupportBundle LINKAGE_BUNDLE = StatementSupportBundle
+ .derivedFrom(PRE_LINKAGE_BUNDLE)
.addSupport(new DescriptionStatementImpl.Definition())
.addSupport(new RevisionStatementImpl.Definition())
.addSupport(new RevisionDateStatementImpl.Definition())
.addSupport(sourceLocal(URIStringToImpPrefix.class))
.addSupport(sourceLocal(BelongsToModuleContext.class))
.addSupport(sourceLocal(QNameToStatementDefinition.class))
- .addSupport(sourceLocal(BelongsToPrefixToModuleName.class)).build();
-
+ .addSupport(sourceLocal(BelongsToPrefixToModuleName.class))
+ .build();
private static final StatementSupportBundle STMT_DEF_BUNDLE = StatementSupportBundle
.derivedFrom(LINKAGE_BUNDLE)
public static final Map<ModelProcessingPhase, StatementSupportBundle> RFC6020_BUNDLES = ImmutableMap
.<ModelProcessingPhase, StatementSupportBundle> builder()
+ .put(ModelProcessingPhase.SOURCE_PRE_LINKAGE, PRE_LINKAGE_BUNDLE)
.put(ModelProcessingPhase.SOURCE_LINKAGE, LINKAGE_BUNDLE)
.put(ModelProcessingPhase.STATEMENT_DEFINITION, STMT_DEF_BUNDLE)
.put(ModelProcessingPhase.FULL_DECLARATION, FULL_DECL_BUNDLE)
public static final CrossSourceStatementReactor RFC6020_REACTOR = CrossSourceStatementReactor
.builder()
.setBundle(ModelProcessingPhase.INIT, INIT_BUNDLE)
+ .setBundle(ModelProcessingPhase.SOURCE_PRE_LINKAGE, PRE_LINKAGE_BUNDLE)
.setBundle(ModelProcessingPhase.SOURCE_LINKAGE, LINKAGE_BUNDLE)
.setBundle(ModelProcessingPhase.STATEMENT_DEFINITION,
STMT_DEF_BUNDLE)
import org.antlr.v4.runtime.ANTLRInputStream;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.tree.ParseTreeWalker;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
import org.opendaylight.yangtools.antlrv4.code.gen.YangStatementLexer;
import org.opendaylight.yangtools.antlrv4.code.gen.YangStatementParser;
import org.opendaylight.yangtools.antlrv4.code.gen.YangStatementParser.StatementContext;
import org.opendaylight.yangtools.yang.parser.spi.source.StatementStreamSource;
import org.opendaylight.yangtools.yang.parser.spi.source.StatementWriter;
import org.opendaylight.yangtools.yang.parser.util.NamedFileInputStream;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
*
}
@Override
- public void writeLinkage(final StatementWriter writer, final QNameToStatementDefinition stmtDef) {
+ public void writePreLinkage(final StatementWriter writer, final QNameToStatementDefinition stmtDef) {
yangStatementModelParser.setAttributes(writer, stmtDef);
walker.walk(yangStatementModelParser, statementContext);
}
+ @Override
+ public void writeLinkage(final StatementWriter writer, final QNameToStatementDefinition stmtDef, final PrefixToModule preLinkagePrefixes) {
+ yangStatementModelParser.setAttributes(writer, stmtDef, preLinkagePrefixes);
+ walker.walk(yangStatementModelParser, statementContext);
+ }
+
@Override
public void writeLinkageAndStatementDefinitions(final StatementWriter writer, final QNameToStatementDefinition stmtDef, final PrefixToModule prefixes) {
yangStatementModelParser.setAttributes(writer, stmtDef, prefixes);
}
@Override
- public void writeLinkage(StatementWriter writer, QNameToStatementDefinition stmtDef) {
+ public void writePreLinkage(StatementWriter writer, QNameToStatementDefinition stmtDef) {
initializeReader();
yinStatementModelParser.setAttributes(writer, stmtDef);
yinStatementModelParser.walk(streamReader);
}
+ @Override
+ public void writeLinkage(StatementWriter writer, QNameToStatementDefinition stmtDef, final PrefixToModule preLinkagePrefixes) {
+ initializeReader();
+ yinStatementModelParser.setAttributes(writer, stmtDef, preLinkagePrefixes);
+ yinStatementModelParser.walk(streamReader);
+ }
+
@Override
public void writeLinkageAndStatementDefinitions(StatementWriter writer, QNameToStatementDefinition stmtDef,
PrefixToModule prefixes) {
return new NamedFileInputStream(file, fileName);
}
-}
+}
\ No newline at end of file
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.ModelProcessingPhase;
import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
fail("reactor.process should fail due to missing imported source");
} catch (ReactorException e) {
assertTrue(e instanceof SomeModifiersUnresolvedException);
- assertEquals(ModelProcessingPhase.SOURCE_LINKAGE, e.getPhase());
+ assertEquals(ModelProcessingPhase.SOURCE_PRE_LINKAGE, e.getPhase());
}
}
fail("reactor.process should fail due to circular import");
} catch (ReactorException e) {
assertTrue(e instanceof SomeModifiersUnresolvedException);
- assertEquals(ModelProcessingPhase.SOURCE_LINKAGE, e.getPhase());
+ assertEquals(ModelProcessingPhase.SOURCE_PRE_LINKAGE, e.getPhase());
}
}
fail("reactor.process should fail due to self import");
} catch (ReactorException e) {
assertTrue(e instanceof SomeModifiersUnresolvedException);
- assertEquals(ModelProcessingPhase.SOURCE_LINKAGE, e.getPhase());
+ assertEquals(ModelProcessingPhase.SOURCE_PRE_LINKAGE, e.getPhase());
}
}
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
+
+import com.google.common.base.VerifyException;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.opendaylight.yangtools.yang.model.api.Module;
-import org.opendaylight.yangtools.yang.parser.spi.meta.MissingSubstatementException;
import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
import org.opendaylight.yangtools.yang.stmt.TestUtils;
@Test
public void missingElementException() throws URISyntaxException, ReactorException {
- expectedEx.expect(MissingSubstatementException.class);
+ expectedEx.expect(VerifyException.class);
Set<Module> modules = TestUtils.loadModules(getClass().getResource
("/substatement-validator/missing-element").toURI());