*/
package org.opendaylight.yangtools.yang.model.api.meta;
+import static java.util.Objects.requireNonNull;
+
import com.google.common.annotations.Beta;
+import com.google.common.collect.ImmutableMap;
import java.util.Collection;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Stream;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
+import org.eclipse.jdt.annotation.NonNull;
/**
* Effective model statement which should be used to derive application behaviour.
/**
* Returns all local values from supplied namespace.
*
- * @param <K>
- * Identifier type
- * @param <V>
- * Value type
- * @param <N>
- * Namespace identifier type
- * @param namespace
- * Namespace type
+ * @param <K> Identifier type
+ * @param <V> Value type
+ * @param <N> Namespace identifier type
+ * @param namespace Namespace type
* @return Value if present, null otherwise.
*/
@Nullable
<K, V, N extends IdentifierNamespace<K, V>> Map<K, V> getAll(@Nonnull Class<N> namespace);
+ /**
+ * Returns all local values from supplied namespace.
+ *
+ * @param <K> Identifier type
+ * @param <V> Value type
+ * @param <N> Namespace identifier type
+ * @param namespace Namespace type
+ * @return Key-value mappings, empty if the namespace does not exist.
+ */
+ default <K, V, N extends IdentifierNamespace<K, V>> @NonNull Map<K, V> findAll(@NonNull final Class<N> namespace) {
+ final Map<K, V> map = getAll(requireNonNull(namespace));
+ return map == null ? ImmutableMap.of() : map;
+ }
+
/**
* Returns a collection of all effective substatements.
*
/**
* Model specific namespace which allows access to specific
*
- * {@link IdentifierNamespace} serves as common superclass for YANG model
- * namespaces, which are type-captured subclasses. This type capture
- * of namespace allows for handy type-safe reading methods
- * such as {@link EffectiveStatement#get(Class, Object)} and still
- * allows introduction of new namespaces without need to change
+ * {@link IdentifierNamespace} serves as common superclass for YANG model namespaces, which are type-captured
+ * subclasses. This type capture of namespace allows for handy type-safe reading methods such as
+ * {@link EffectiveStatement#get(Class, Object)} and still allows introduction of new namespaces without need to change
* model APIs.
*
* @param <K> Identifier type
* @param <V> Value type
*/
-public interface IdentifierNamespace<K,V> {
+public interface IdentifierNamespace<K, V> {
/**
* Returns value associated with supplied identifier.
*
package org.opendaylight.yangtools.yang.model.api.stmt;
import com.google.common.annotations.Beta;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.yangtools.yang.common.QNameModule;
import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.meta.IdentifierNamespace;
@Beta
public interface ModuleEffectiveStatement extends EffectiveStatement<String, ModuleStatement> {
+ /**
+ * Namespace mapping all known prefixes in a module to their modules. Note this namespace includes the module
+ * in which it is instantiated.
+ */
+ abstract class PrefixToEffectiveModuleNamespace implements IdentifierNamespace<String, ModuleEffectiveStatement> {
+ private PrefixToEffectiveModuleNamespace() {
+ // This class should never be subclassed
+ }
+ }
+ /**
+ * Namespace mapping all known {@link QNameModule}s to their encoding prefixes. This includes the declaration
+ * from prefix/namespace/revision and all imports as they were resolved.
+ */
+ abstract class QNameModuleToPrefixNamespace implements IdentifierNamespace<QNameModule, String> {
+ private QNameModuleToPrefixNamespace() {
+ // This class should never be subclassed
+ }
+ }
+
+ /**
+ * Get the local QNameModule of this module. All implementations need to override this default method.
+ *
+ * @return Local QNameModule
+ */
+ // FIXME: 3.0.0 make this method non-default
+ default @NonNull QNameModule localQNameModule() {
+ throw new UnsupportedOperationException(getClass() + " is missing an implementation");
+ }
}
*/
package org.opendaylight.yangtools.yang.parser.rfc7950.stmt;
+import static java.util.Objects.requireNonNull;
+
+import com.google.common.annotations.Beta;
import com.google.common.collect.Collections2;
import com.google.common.collect.ImmutableList;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.function.Predicate;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
+import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.yangtools.yang.model.api.SchemaNode;
import org.opendaylight.yangtools.yang.model.api.YangStmtMapping;
import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
@Override
public final <K, V, N extends IdentifierNamespace<K, V>> V get(@Nonnull final Class<N> namespace,
@Nonnull final K identifier) {
- throw new UnsupportedOperationException("Not implemented yet.");
+ return findAll(namespace).get(requireNonNull(identifier));
}
@Override
public final <K, V, N extends IdentifierNamespace<K, V>> Map<K, V> getAll(@Nonnull final Class<N> namespace) {
- throw new UnsupportedOperationException("Not implemented yet.");
+ return getNamespaceContents(requireNonNull(namespace)).orElse(null);
+ }
+
+ /**
+ * Return the statement-specific contents of specified namespace, if available.
+ *
+ * @param namespace Requested namespace
+ * @return Namespace contents, if available.
+ */
+ @Beta
+ protected <K, V, N extends IdentifierNamespace<K, V>> Optional<? extends Map<K, V>> getNamespaceContents(
+ final @NonNull Class<N> namespace) {
+ return Optional.empty();
}
@Nonnull
*/
package org.opendaylight.yangtools.yang.parser.rfc7950.stmt.module;
-import com.google.common.base.Verify;
+import static com.google.common.base.Verify.verifyNotNull;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableMap.Builder;
+import com.google.common.collect.Maps;
+import java.util.Map;
+import java.util.Map.Entry;
import java.util.Objects;
+import java.util.Optional;
+import org.eclipse.jdt.annotation.NonNull;
import org.opendaylight.yangtools.yang.common.QNameModule;
import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.meta.IdentifierNamespace;
+import org.opendaylight.yangtools.yang.model.api.stmt.ImportEffectiveStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.ModuleEffectiveStatement;
import org.opendaylight.yangtools.yang.model.api.stmt.ModuleStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.PrefixEffectiveStatement;
import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.AbstractEffectiveModule;
import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
+import org.opendaylight.yangtools.yang.parser.spi.source.ImportPrefixToModuleCtx;
import org.opendaylight.yangtools.yang.parser.spi.source.ModuleCtxToModuleQName;
final class ModuleEffectiveStatementImpl extends AbstractEffectiveModule<ModuleStatement>
implements ModuleEffectiveStatement {
- private final QNameModule qnameModule;
+ private final Map<String, ModuleEffectiveStatement> prefixToModule;
+ private final Map<QNameModule, String> namespaceToPrefix;
+ private final @NonNull QNameModule qnameModule;
ModuleEffectiveStatementImpl(
final StmtContext<String, ModuleStatement, EffectiveStatement<String, ModuleStatement>> ctx) {
super(ctx);
- qnameModule = Verify.verifyNotNull(ctx.getFromNamespace(ModuleCtxToModuleQName.class, ctx));
+ qnameModule = verifyNotNull(ctx.getFromNamespace(ModuleCtxToModuleQName.class, ctx));
+
+ final String localPrefix = findFirstEffectiveSubstatementArgument(PrefixEffectiveStatement.class).get();
+ final Builder<String, ModuleEffectiveStatement> prefixToModuleBuilder = ImmutableMap.builder();
+ prefixToModuleBuilder.put(localPrefix, this);
+
+ streamEffectiveSubstatements(ImportEffectiveStatement.class)
+ .map(imp -> imp.findFirstEffectiveSubstatementArgument(PrefixEffectiveStatement.class).get())
+ .forEach(prefix -> {
+ final StmtContext<?, ?, ?> importedCtx =
+ verifyNotNull(ctx.getFromNamespace(ImportPrefixToModuleCtx.class, prefix),
+ "Failed to resolve prefix %s", prefix);
+ prefixToModuleBuilder.put(prefix, (ModuleEffectiveStatement) importedCtx.buildEffective());
+ });
+ prefixToModule = prefixToModuleBuilder.build();
+
+ final Map<QNameModule, String> tmp = Maps.newLinkedHashMapWithExpectedSize(prefixToModule.size() + 1);
+ tmp.put(qnameModule, localPrefix);
+ for (Entry<String, ModuleEffectiveStatement> e : prefixToModule.entrySet()) {
+ tmp.putIfAbsent(e.getValue().localQNameModule(), e.getKey());
+ }
+ namespaceToPrefix = ImmutableMap.copyOf(tmp);
}
@Override
- public QNameModule getQNameModule() {
+ public @NonNull QNameModule localQNameModule() {
return qnameModule;
}
+ @Override
+ public @NonNull QNameModule getQNameModule() {
+ return qnameModule;
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public <K, V, N extends IdentifierNamespace<K, V>> Optional<? extends Map<K, V>> getNamespaceContents(
+ final @NonNull Class<N> namespace) {
+ if (PrefixToEffectiveModuleNamespace.class.equals(namespace)) {
+ return Optional.of((Map<K, V>) prefixToModule);
+ }
+ if (QNameModuleToPrefixNamespace.class.equals(namespace)) {
+ return Optional.of((Map<K, V>) namespaceToPrefix);
+ }
+ return super.getNamespaceContents(namespace);
+ }
+
@Override
public int hashCode() {
final int prime = 31;
}
return true;
}
-
}