private final ImmutableMap<QName, StatementSupport<?,?,?>> definitions;
private final ImmutableMap<Class<?>, NamespaceBehaviour<?, ?, ?>> namespaceDefinitions;
- private StatementSupportBundle(StatementSupportBundle parent,
- ImmutableMap<QName, StatementSupport<?, ?, ?>> statements,
- ImmutableMap<Class<?>, NamespaceBehaviour<?, ?, ?>> namespaces) {
+ private StatementSupportBundle(final StatementSupportBundle parent,
+ final ImmutableMap<QName, StatementSupport<?, ?, ?>> statements,
+ final ImmutableMap<Class<?>, NamespaceBehaviour<?, ?, ?>> namespaces) {
this.parent = parent;
this.definitions = statements;
this.namespaceDefinitions = namespaces;
return definitions;
}
+ public ImmutableMap<Class<?>, NamespaceBehaviour<?, ?, ?>> getNamespaceDefinitions() {
+ return namespaceDefinitions;
+ }
+
public static Builder builder() {
return new Builder(EMPTY);
}
- public static Builder derivedFrom(StatementSupportBundle parent) {
+ public static Builder derivedFrom(final StatementSupportBundle parent) {
return new Builder(parent);
}
@Override
- public <K, V, N extends IdentifierNamespace<K, V>> NamespaceBehaviour<K, V, N> getNamespaceBehaviour(Class<N> namespace)
+ public <K, V, N extends IdentifierNamespace<K, V>> NamespaceBehaviour<K, V, N> getNamespaceBehaviour(final Class<N> namespace)
throws NamespaceNotAvailableException {
- NamespaceBehaviour<?, ?, ?> potential = namespaceDefinitions.get(namespace);
+ final NamespaceBehaviour<?, ?, ?> potential = namespaceDefinitions.get(namespace);
if (potential != null) {
Preconditions.checkState(namespace.equals(potential.getIdentifier()));
return null;
}
- public <K, V, N extends IdentifierNamespace<K, V>> boolean hasNamespaceBehaviour(Class<N> namespace) {
+ public <K, V, N extends IdentifierNamespace<K, V>> boolean hasNamespaceBehaviour(final Class<N> namespace) {
if (namespaceDefinitions.containsKey(namespace)) {
return true;
}
return false;
}
- public StatementSupport<?, ?,?> getStatementDefinition(QName stmtName) {
- StatementSupport<?,?, ?> potential = definitions.get(stmtName);
+ public StatementSupport<?, ?,?> getStatementDefinition(final QName stmtName) {
+ final StatementSupport<?,?, ?> potential = definitions.get(stmtName);
if (potential != null) {
return potential;
}
public static class Builder implements org.opendaylight.yangtools.concepts.Builder<StatementSupportBundle> {
- private final StatementSupportBundle parent;
- private final Map<QName, StatementSupport<?,?,?>> statements = new HashMap<>();
+ private StatementSupportBundle parent;
+ private final Map<QName, StatementSupport<?, ?, ?>> statements = new HashMap<>();
private final Map<Class<?>, NamespaceBehaviour<?, ?, ?>> namespaces = new HashMap<>();
- Builder(StatementSupportBundle parent) {
+ Builder(final StatementSupportBundle parent) {
this.parent = parent;
}
- public Builder addSupport(StatementSupport<?, ?,?> definition) {
- QName identifier = definition.getStatementName();
- Preconditions.checkState(!statements.containsKey(identifier), "Statement %s already defined.",identifier);
- Preconditions.checkState(parent.getStatementDefinition(identifier) == null, "Statement %s already defined.",identifier);
+ public Builder addSupport(final StatementSupport<?, ?, ?> definition) {
+ final QName identifier = definition.getStatementName();
+ Preconditions.checkState(!statements.containsKey(identifier), "Statement %s already defined.", identifier);
+ Preconditions.checkState(parent.getStatementDefinition(identifier) == null,
+ "Statement %s already defined.", identifier);
statements.put(identifier, definition);
return this;
}
- public <K, V, N extends IdentifierNamespace<K, V>> Builder addSupport(NamespaceBehaviour<K, V, N> namespaceSupport) {
- Class<N> identifier = namespaceSupport.getIdentifier();
+ public <K, V, N extends IdentifierNamespace<K, V>> Builder addSupport(
+ final NamespaceBehaviour<K, V, N> namespaceSupport) {
+ final Class<N> identifier = namespaceSupport.getIdentifier();
Preconditions.checkState(!namespaces.containsKey(identifier));
Preconditions.checkState(!parent.hasNamespaceBehaviour(identifier));
namespaces.put(identifier, namespaceSupport);
return this;
}
- @Override
+ public Builder setParent(final StatementSupportBundle parent) {
+ this.parent = parent;
+ return this;
+ }
+
+ @Override
public StatementSupportBundle build() {
return new StatementSupportBundle(parent, ImmutableMap.copyOf(statements), ImmutableMap.copyOf(namespaces));
}
public interface ValidationBundlesNamespace extends
IdentifierNamespace<ValidationBundlesNamespace.ValidationBundleType, Collection<?>> {
- enum ValidationBundleType {
+ public enum ValidationBundleType {
/**
* whether a node is suitable refine substatement
*/
--- /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.stmt.reactor;
+
+import com.google.common.collect.ImmutableMap;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Map.Entry;
+import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
+import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase;
+import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StatementSupport;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StatementSupportBundle;
+import org.opendaylight.yangtools.yang.parser.spi.validation.ValidationBundlesNamespace.ValidationBundleType;
+import org.opendaylight.yangtools.yang.parser.stmt.reactor.CrossSourceStatementReactor.Builder;
+import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.YangInferencePipeline;
+
+public class CustomStatementParserBuilder {
+ private final Map<ModelProcessingPhase, StatementSupportBundle.Builder> reactorSupportBundles = ImmutableMap
+ .<ModelProcessingPhase, StatementSupportBundle.Builder> builder()
+ .put(ModelProcessingPhase.INIT, StatementSupportBundle.builder())
+ .put(ModelProcessingPhase.SOURCE_PRE_LINKAGE, StatementSupportBundle.builder())
+ .put(ModelProcessingPhase.SOURCE_LINKAGE, StatementSupportBundle.builder())
+ .put(ModelProcessingPhase.STATEMENT_DEFINITION, StatementSupportBundle.builder())
+ .put(ModelProcessingPhase.FULL_DECLARATION, StatementSupportBundle.builder())
+ .put(ModelProcessingPhase.EFFECTIVE_MODEL, StatementSupportBundle.builder()).build();
+ private final Map<ValidationBundleType, Collection<StatementDefinition>> reactorValidationBundles = new HashMap<>();
+
+ public CustomStatementParserBuilder addStatementSupport(final ModelProcessingPhase phase,
+ final StatementSupport<?, ?, ?> stmtSupport) {
+ reactorSupportBundles.get(phase).addSupport(stmtSupport);
+ return this;
+ }
+
+ public CustomStatementParserBuilder addNamespaceSupport(final ModelProcessingPhase phase,
+ final NamespaceBehaviour<?, ?, ?> namespaceSupport) {
+ reactorSupportBundles.get(phase).addSupport(namespaceSupport);
+ return this;
+ }
+
+ public CustomStatementParserBuilder addDefaultRFC6020Bundles() {
+ addRFC6020SupportBundles();
+ addRFC6020ValidationBundles();
+ return this;
+ }
+
+ private void addRFC6020ValidationBundles() {
+ reactorValidationBundles.putAll(YangInferencePipeline.RFC6020_VALIDATION_BUNDLE);
+ }
+
+ private void addRFC6020SupportBundles() {
+ for (final Entry<ModelProcessingPhase, StatementSupportBundle> entry : YangInferencePipeline.RFC6020_BUNDLES
+ .entrySet()) {
+ addAllSupports(entry.getKey(), entry.getValue());
+ }
+ }
+
+ public CustomStatementParserBuilder addValidationBundle(final ValidationBundleType validationBundleType,
+ final Collection<StatementDefinition> validationBundle) {
+ reactorValidationBundles.put(validationBundleType, validationBundle);
+ return this;
+ }
+
+ public CustomStatementParserBuilder addAllSupports(final ModelProcessingPhase phase,
+ final StatementSupportBundle stmtSupportBundle) {
+ addAllStatementSupports(phase, stmtSupportBundle.getDefinitions().values());
+ addAllNamespaceSupports(phase, stmtSupportBundle.getNamespaceDefinitions().values());
+ return this;
+ }
+
+ public CustomStatementParserBuilder addAllNamespaceSupports(final ModelProcessingPhase phase,
+ final Collection<NamespaceBehaviour<?, ?, ?>> namespaceSupports) {
+ final StatementSupportBundle.Builder stmtBundleBuilder = reactorSupportBundles.get(phase);
+ for (final NamespaceBehaviour<?, ?, ?> namespaceSupport : namespaceSupports) {
+ stmtBundleBuilder.addSupport(namespaceSupport);
+ }
+ return this;
+ }
+
+ public CustomStatementParserBuilder addAllStatementSupports(final ModelProcessingPhase phase,
+ final Collection<StatementSupport<?, ?, ?>> statementSupports) {
+ final StatementSupportBundle.Builder stmtBundleBuilder = reactorSupportBundles.get(phase);
+ for (final StatementSupport<?, ?, ?> statementSupport : statementSupports) {
+ stmtBundleBuilder.addSupport(statementSupport);
+ }
+ return this;
+ }
+
+ public CrossSourceStatementReactor build() {
+ final StatementSupportBundle initBundle = reactorSupportBundles.get(ModelProcessingPhase.INIT).build();
+ final StatementSupportBundle preLinkageBundle = reactorSupportBundles
+ .get(ModelProcessingPhase.SOURCE_PRE_LINKAGE).setParent(initBundle).build();
+ final StatementSupportBundle linkageBundle = reactorSupportBundles.get(ModelProcessingPhase.SOURCE_LINKAGE)
+ .setParent(preLinkageBundle).build();
+ final StatementSupportBundle stmtDefBundle = reactorSupportBundles
+ .get(ModelProcessingPhase.STATEMENT_DEFINITION).setParent(linkageBundle).build();
+ final StatementSupportBundle fullDeclBundle = reactorSupportBundles.get(ModelProcessingPhase.FULL_DECLARATION)
+ .setParent(stmtDefBundle).build();
+ final StatementSupportBundle effectiveBundle = reactorSupportBundles.get(ModelProcessingPhase.EFFECTIVE_MODEL)
+ .setParent(fullDeclBundle).build();
+
+ final Builder reactorBuilder = CrossSourceStatementReactor.builder()
+ .setBundle(ModelProcessingPhase.INIT, initBundle)
+ .setBundle(ModelProcessingPhase.SOURCE_PRE_LINKAGE, preLinkageBundle)
+ .setBundle(ModelProcessingPhase.SOURCE_LINKAGE, linkageBundle)
+ .setBundle(ModelProcessingPhase.STATEMENT_DEFINITION, stmtDefBundle)
+ .setBundle(ModelProcessingPhase.FULL_DECLARATION, fullDeclBundle)
+ .setBundle(ModelProcessingPhase.EFFECTIVE_MODEL, effectiveBundle);
+
+ for (final Entry<ValidationBundleType, Collection<StatementDefinition>> entry : reactorValidationBundles
+ .entrySet()) {
+ reactorBuilder.setValidationBundle(entry.getKey(), entry.getValue());
+ }
+
+ return reactorBuilder.build();
+ }
+}
extends NamespaceBehaviour<QName, StmtContext<?, D, E>, ChildSchemaNodes<D, E>>
implements StatementNamespace<QName, D, E>{
- protected ChildSchemaNodes() {
+ public ChildSchemaNodes() {
super((Class) ChildSchemaNodes.class);
}
import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext.Mutable;
import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContextUtils;
-class SchemaNodeIdentifierBuildNamespace extends
+public class SchemaNodeIdentifierBuildNamespace extends
DerivedNamespaceBehaviour<SchemaNodeIdentifier, StmtContext.Mutable<?, ?, EffectiveStatement<?, ?>>, QName, SchemaNodeIdentifierBuildNamespace, ChildSchemaNodes<?, ?>>
implements IdentifierNamespace<SchemaNodeIdentifier, StmtContext.Mutable<?, ?, EffectiveStatement<?, ?>>> {
@SuppressWarnings({"unchecked", "rawtypes"})
- protected SchemaNodeIdentifierBuildNamespace() {
+ public SchemaNodeIdentifierBuildNamespace() {
super(SchemaNodeIdentifierBuildNamespace.class, (Class) ChildSchemaNodes.class);
}
@Override
public StmtContext.Mutable<?, ?, EffectiveStatement<?, ?>> get(
- SchemaNodeIdentifier key) {
+ final SchemaNodeIdentifier key) {
throw new UnsupportedOperationException("Direct access to namespace is not supported");
}
@SuppressWarnings("unchecked")
@Override
- public StmtContext.Mutable<?, ?, EffectiveStatement<?, ?>> getFrom(NamespaceStorageNode storage, SchemaNodeIdentifier key) {
+ public StmtContext.Mutable<?, ?, EffectiveStatement<?, ?>> getFrom(final NamespaceStorageNode storage, final SchemaNodeIdentifier key) {
final NamespaceStorageNode lookupStartStorage;
if (key.isAbsolute() || storage.getStorageNodeType() == StorageNodeType.ROOT_STATEMENT_LOCAL) {
} else {
lookupStartStorage = storage;
}
- Iterator<QName> iterator = key.getPathFromRoot().iterator();
+ final Iterator<QName> iterator = key.getPathFromRoot().iterator();
if (!iterator.hasNext()) {
if (lookupStartStorage instanceof StmtContext<?, ?, ?>) {
return (StmtContext.Mutable<?, ?, EffectiveStatement<?, ?>>) lookupStartStorage;
}
while (current != null && iterator.hasNext()) {
nextPath = iterator.next();
- StmtContext.Mutable<?, ?, EffectiveStatement<?, ?>> nextNodeCtx = (StmtContext.Mutable<?, ?, EffectiveStatement<?, ?>>) current
+ final StmtContext.Mutable<?, ?, EffectiveStatement<?, ?>> nextNodeCtx = (StmtContext.Mutable<?, ?, EffectiveStatement<?, ?>>) current
.getFromNamespace(ChildSchemaNodes.class, nextPath);
if (nextNodeCtx == null) {
return tryToFindUnknownStatement(nextPath.getLocalName(), current);
@SuppressWarnings({"unchecked", "rawtypes"})
private Mutable<?, ?, EffectiveStatement<?, ?>> tryToFindUnknownStatement(final String localName,
final Mutable<?, ?, EffectiveStatement<?, ?>> current) {
- Collection<StmtContext<?, ?, ?>> unknownSubstatements = (Collection)StmtContextUtils.findAllSubstatements(current,
+ final Collection<StmtContext<?, ?, ?>> unknownSubstatements = (Collection)StmtContextUtils.findAllSubstatements(current,
UnknownStatement.class);
- for (StmtContext<?, ?, ?> unknownSubstatement : unknownSubstatements) {
+ for (final StmtContext<?, ?, ?> unknownSubstatement : unknownSubstatements) {
if (localName.equals(unknownSubstatement.rawStatementArgument())) {
return (Mutable<?, ?, EffectiveStatement<?, ?>>) unknownSubstatement;
}
}
@Override
- public QName getSignificantKey(SchemaNodeIdentifier key) {
+ public QName getSignificantKey(final SchemaNodeIdentifier key) {
return key.getLastComponent();
}
import org.opendaylight.yangtools.yang.model.api.meta.IdentifierNamespace;
/**
- * Implementation-internal cache for looking up URI -> import prefix. URIs are taken in as Strings to save ourselves
+ * Implementation-internal cache for looking up URI to import prefix. URIs are taken in as Strings to save ourselves
* some quality parsing time.
*/
-interface URIStringToImpPrefix extends IdentifierNamespace<String, String> {
+public interface URIStringToImpPrefix extends IdentifierNamespace<String, String> {
}
import static org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour.treeScoped;
import com.google.common.collect.ImmutableMap;
+import java.util.Collection;
import java.util.Map;
+import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
import org.opendaylight.yangtools.yang.parser.spi.ExtensionNamespace;
import org.opendaylight.yangtools.yang.parser.spi.GroupingNamespace;
import org.opendaylight.yangtools.yang.parser.spi.IdentityNamespace;
.addSupport(sourceLocal(ImpPrefixToSemVerModuleIdentifier.class))
.build();
- private static final StatementSupportBundle STMT_DEF_BUNDLE = StatementSupportBundle
+ public static final StatementSupportBundle STMT_DEF_BUNDLE = StatementSupportBundle
.derivedFrom(LINKAGE_BUNDLE)
.addSupport(new YinElementStatementImpl.Definition())
.addSupport(new ArgumentStatementImpl.Definition())
.addSupport(global(DerivedIdentitiesNamespace.class))
.build();
- private static final StatementSupportBundle FULL_DECL_BUNDLE = StatementSupportBundle
+ public static final StatementSupportBundle FULL_DECL_BUNDLE = StatementSupportBundle
.derivedFrom(STMT_DEF_BUNDLE)
.addSupport(new LeafStatementImpl.Definition())
.addSupport(new ConfigStatementImpl.Definition())
public static final Map<ModelProcessingPhase, StatementSupportBundle> RFC6020_BUNDLES = ImmutableMap
.<ModelProcessingPhase, StatementSupportBundle> builder()
+ .put(ModelProcessingPhase.INIT, INIT_BUNDLE)
.put(ModelProcessingPhase.SOURCE_PRE_LINKAGE, PRE_LINKAGE_BUNDLE)
.put(ModelProcessingPhase.SOURCE_LINKAGE, LINKAGE_BUNDLE)
.put(ModelProcessingPhase.STATEMENT_DEFINITION, STMT_DEF_BUNDLE)
.put(ModelProcessingPhase.EFFECTIVE_MODEL, FULL_DECL_BUNDLE)
.build();
+ public static final Map<ValidationBundleType, Collection<StatementDefinition>> RFC6020_VALIDATION_BUNDLE = ImmutableMap
+ .<ValidationBundleType, Collection<StatementDefinition>> builder()
+ .put(ValidationBundleType.SUPPORTED_REFINE_SUBSTATEMENTS, YangValidationBundles.SUPPORTED_REFINE_SUBSTATEMENTS)
+ .put(ValidationBundleType.SUPPORTED_AUGMENT_TARGETS, YangValidationBundles.SUPPORTED_AUGMENT_TARGETS)
+ .put(ValidationBundleType.SUPPORTED_CASE_SHORTHANDS, YangValidationBundles.SUPPORTED_CASE_SHORTHANDS)
+ .put(ValidationBundleType.SUPPORTED_DATA_NODES, YangValidationBundles.SUPPORTED_DATA_NODES)
+ .build();
+
public static final CrossSourceStatementReactor RFC6020_REACTOR = CrossSourceStatementReactor
.builder()
.setBundle(ModelProcessingPhase.INIT, INIT_BUNDLE)
--- /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.thirdparty.plugin;
+
+import static org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour.sourceLocal;
+
+import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase;
+import org.opendaylight.yangtools.yang.parser.stmt.reactor.CrossSourceStatementReactor;
+import org.opendaylight.yangtools.yang.parser.stmt.reactor.CustomStatementParserBuilder;
+
+public final class CustomInferencePipeline {
+ public static final CrossSourceStatementReactor CUSTOM_REACTOR = new CustomStatementParserBuilder()
+ .addDefaultRFC6020Bundles()
+ .addStatementSupport(ModelProcessingPhase.FULL_DECLARATION,
+ new ThirdPartyExtensionStatementImpl.ThirdPartyExtensionSupport())
+ .addNamespaceSupport(ModelProcessingPhase.FULL_DECLARATION, sourceLocal(ThirdPartyNamespace.class))
+ .build();
+
+ private CustomInferencePipeline() {
+ throw new UnsupportedOperationException("Utility class");
+ }
+}
--- /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.thirdparty.plugin;
+
+import com.google.common.annotations.Beta;
+import java.util.Objects;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+import org.opendaylight.yangtools.yang.model.api.stmt.UnknownStatement;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
+import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.UnknownEffectiveStatementBase;
+
+@Beta
+public final class ThirdPartyExtensionEffectiveStatementImpl extends UnknownEffectiveStatementBase<String> {
+
+ private final SchemaPath path;
+ private final String valueFromNamespace;
+
+ public ThirdPartyExtensionEffectiveStatementImpl(final StmtContext<String, UnknownStatement<String>, ?> ctx) {
+ super(ctx);
+ path = ctx.getParentContext().getSchemaPath().get().createChild(getNodeType());
+ valueFromNamespace = ctx.getFromNamespace(ThirdPartyNamespace.class, ctx);
+ }
+
+ public String getValueFromNamespace() {
+ return valueFromNamespace;
+ }
+
+ @Override
+ public QName getQName() {
+ return getNodeType();
+ }
+
+ @Override
+ public SchemaPath getPath() {
+ return path;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(path, getNodeType(), getNodeParameter());
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final ThirdPartyExtensionEffectiveStatementImpl other = (ThirdPartyExtensionEffectiveStatementImpl) obj;
+ if (!Objects.equals(path, other.path)) {
+ return false;
+ }
+ if (!Objects.equals(getNodeType(), other.getNodeType())) {
+ return false;
+ }
+ if (!Objects.equals(getNodeParameter(), other.getNodeParameter())) {
+ return false;
+ }
+ return true;
+ }
+}
--- /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.thirdparty.plugin;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.net.URISyntaxException;
+import java.util.List;
+import org.junit.Test;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
+import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
+import org.opendaylight.yangtools.yang.parser.stmt.reactor.CrossSourceStatementReactor;
+import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.YangStatementSourceImpl;
+import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective.EffectiveSchemaContext;
+
+public class ThirdPartyExtensionPluginTest {
+ private static final String NS = "urn:opendaylight:yang:extension:third-party";
+ private static final String REV = "2016-06-09";
+
+ @Test
+ public void test() throws FileNotFoundException, URISyntaxException, ReactorException {
+ final CrossSourceStatementReactor.BuildAction reactor = CustomInferencePipeline.CUSTOM_REACTOR.newBuild();
+ final FileInputStream yangFile = new FileInputStream(new File(getClass().getResource("/plugin-test/foo.yang")
+ .toURI()));
+ reactor.addSource(new YangStatementSourceImpl(yangFile));
+
+ final EffectiveSchemaContext schema = reactor.buildEffective();
+ final DataSchemaNode dataChildByName = schema.getDataChildByName(QName.create(NS, REV, "root"));
+ assertTrue(dataChildByName instanceof ContainerSchemaNode);
+ final ContainerSchemaNode root = (ContainerSchemaNode) dataChildByName;
+
+ final List<UnknownSchemaNode> unknownSchemaNodes = root.getUnknownSchemaNodes();
+ assertEquals(1, unknownSchemaNodes.size());
+
+ final UnknownSchemaNode unknownSchemaNode = unknownSchemaNodes.get(0);
+ assertTrue(unknownSchemaNode instanceof ThirdPartyExtensionEffectiveStatementImpl);
+
+ final ThirdPartyExtensionEffectiveStatementImpl thirdPartyExtensionStmt = (ThirdPartyExtensionEffectiveStatementImpl) unknownSchemaNode;
+ assertEquals("Third-party namespace test.", thirdPartyExtensionStmt.getValueFromNamespace());
+ assertEquals("plugin test", thirdPartyExtensionStmt.argument());
+ }
+}
--- /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.thirdparty.plugin;
+
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.UnknownStatement;
+import org.opendaylight.yangtools.yang.parser.spi.meta.AbstractDeclaredStatement;
+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;
+
+public class ThirdPartyExtensionStatementImpl extends AbstractDeclaredStatement<String> implements
+ UnknownStatement<String> {
+
+ ThirdPartyExtensionStatementImpl(final StmtContext<String, UnknownStatement<String>, ?> context) {
+ super(context);
+ }
+
+ public static class ThirdPartyExtensionSupport
+ extends
+ AbstractStatementSupport<String, UnknownStatement<String>, EffectiveStatement<String, UnknownStatement<String>>> {
+
+ public ThirdPartyExtensionSupport() {
+ super(ThirdPartyExtensionsMapping.THIRD_PARTY_EXTENSION);
+ }
+
+ @Override
+ public String parseArgumentValue(final StmtContext<?, ?, ?> ctx, final String value) {
+ return value;
+ }
+
+ @Override
+ public void onFullDefinitionDeclared(
+ final Mutable<String, UnknownStatement<String>, EffectiveStatement<String, UnknownStatement<String>>> stmt) {
+ stmt.addToNs(ThirdPartyNamespace.class, stmt, "Third-party namespace test.");
+ }
+
+ @Override
+ public UnknownStatement<String> createDeclared(final StmtContext<String, UnknownStatement<String>, ?> ctx) {
+ return new ThirdPartyExtensionStatementImpl(ctx);
+ }
+
+ @Override
+ public EffectiveStatement<String, UnknownStatement<String>> createEffective(
+ final StmtContext<String, UnknownStatement<String>, EffectiveStatement<String, UnknownStatement<String>>> ctx) {
+ return new ThirdPartyExtensionEffectiveStatementImpl(ctx);
+ }
+ }
+
+ @Override
+ public String getArgument() {
+ return argument();
+ }
+}
--- /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.thirdparty.plugin;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Preconditions;
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
+
+@Beta
+public enum ThirdPartyExtensionsMapping implements StatementDefinition {
+ THIRD_PARTY_EXTENSION("urn:opendaylight:yang:extension:third-party", "2016-06-09",
+ ThirdPartyExtensionStatementImpl.class, ThirdPartyExtensionEffectiveStatementImpl.class,
+ "third-party-extension", "argument-name", false);
+
+ private final Class<? extends DeclaredStatement<?>> type;
+ private final Class<? extends EffectiveStatement<?, ?>> effectiveType;
+ private final QName name;
+ private final QName argument;
+ private final boolean yinElement;
+
+ ThirdPartyExtensionsMapping(final String namespace, final String revision,
+ final Class<? extends DeclaredStatement<?>> declared,
+ final Class<? extends EffectiveStatement<?, ?>> effective, final String nameStr, final String argumentStr,
+ final boolean yinElement) {
+ type = Preconditions.checkNotNull(declared);
+ effectiveType = Preconditions.checkNotNull(effective);
+ name = createQName(namespace, revision, nameStr);
+ argument = createQName(namespace, revision, argumentStr);
+ this.yinElement = yinElement;
+ }
+
+ private ThirdPartyExtensionsMapping(final String namespace, final Class<? extends DeclaredStatement<?>> declared,
+ final Class<? extends EffectiveStatement<?, ?>> effective, final String nameStr, final String argumentStr,
+ final boolean yinElement) {
+ type = Preconditions.checkNotNull(declared);
+ effectiveType = Preconditions.checkNotNull(effective);
+ name = createQName(namespace, nameStr);
+ argument = createQName(namespace, argumentStr);
+ this.yinElement = yinElement;
+ }
+
+ @Nonnull
+ private static QName createQName(final String namespace, final String localName) {
+ return QName.create(namespace, localName).intern();
+ }
+
+ @Nonnull
+ private static QName createQName(final String namespace, final String revision, final String localName) {
+ return QName.create(namespace, revision, localName).intern();
+ }
+
+ @Override
+ public QName getStatementName() {
+ return name;
+ }
+
+ @Override
+ @Nullable
+ public QName getArgumentName() {
+ return argument;
+ }
+
+ @Override
+ @Nonnull
+ public Class<? extends DeclaredStatement<?>> getDeclaredRepresentationClass() {
+ return type;
+ }
+
+ @Override
+ public Class<? extends EffectiveStatement<?, ?>> getEffectiveRepresentationClass() {
+ return effectiveType;
+ }
+
+ @Override
+ public boolean isArgumentYinElement() {
+ return yinElement;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 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.thirdparty.plugin;
+
+import org.opendaylight.yangtools.yang.model.api.meta.IdentifierNamespace;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
+
+/**
+ *
+ * ThirdPartyNamespace
+ *
+ */
+public interface ThirdPartyNamespace extends IdentifierNamespace<StmtContext<?, ?, ?>, String> {
+
+}
--- /dev/null
+module foo {
+ namespace "urn:opendaylight:yang:extension:third-party";
+ prefix foo;
+ yang-version 1;
+
+ revision 2016-06-09;
+
+ container root {
+ foo:third-party-extension "plugin test";
+ }
+
+ extension third-party-extension {
+ argument argument-name;
+ }
+}