import static org.opendaylight.yangtools.yang.parser.builder.impl.BuilderUtils.findSchemaNode;
import static org.opendaylight.yangtools.yang.parser.builder.impl.BuilderUtils.findSchemaNodeInModule;
import static org.opendaylight.yangtools.yang.parser.builder.impl.BuilderUtils.processAugmentation;
-import static org.opendaylight.yangtools.yang.parser.builder.impl.BuilderUtils.setNodeAddedByUses;
-import static org.opendaylight.yangtools.yang.parser.builder.impl.BuilderUtils.wrapChildNodes;
-import static org.opendaylight.yangtools.yang.parser.builder.impl.BuilderUtils.wrapGroupings;
-import static org.opendaylight.yangtools.yang.parser.builder.impl.BuilderUtils.wrapTypedefs;
-import static org.opendaylight.yangtools.yang.parser.builder.impl.BuilderUtils.wrapUnknownNodes;
import static org.opendaylight.yangtools.yang.parser.builder.impl.TypeUtils.resolveType;
import static org.opendaylight.yangtools.yang.parser.builder.impl.TypeUtils.resolveTypeUnion;
import com.google.common.base.Splitter;
import com.google.common.collect.HashBiMap;
import com.google.common.io.ByteSource;
+
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
-import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
+
import javax.annotation.concurrent.Immutable;
+
import org.antlr.v4.runtime.ANTLRInputStream;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.tree.ParseTree;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.common.QNameModule;
import org.opendaylight.yangtools.yang.model.api.ExtensionDefinition;
-import org.opendaylight.yangtools.yang.model.api.GroupingDefinition;
import org.opendaylight.yangtools.yang.model.api.Module;
import org.opendaylight.yangtools.yang.model.api.ModuleIdentifier;
import org.opendaylight.yangtools.yang.model.api.ModuleImport;
import org.opendaylight.yangtools.yang.parser.builder.api.GroupingBuilder;
import org.opendaylight.yangtools.yang.parser.builder.api.SchemaNodeBuilder;
import org.opendaylight.yangtools.yang.parser.builder.api.TypeAwareBuilder;
-import org.opendaylight.yangtools.yang.parser.builder.api.TypeDefinitionBuilder;
import org.opendaylight.yangtools.yang.parser.builder.api.UnknownSchemaNodeBuilder;
import org.opendaylight.yangtools.yang.parser.builder.api.UsesNodeBuilder;
import org.opendaylight.yangtools.yang.parser.builder.impl.BuilderUtils;
import org.opendaylight.yangtools.yang.parser.builder.impl.ModuleBuilder;
import org.opendaylight.yangtools.yang.parser.builder.impl.ModuleImpl;
import org.opendaylight.yangtools.yang.parser.builder.impl.UnionTypeBuilder;
-import org.opendaylight.yangtools.yang.parser.builder.impl.UnknownSchemaNodeBuilderImpl;
import org.opendaylight.yangtools.yang.parser.builder.util.Comparators;
import org.opendaylight.yangtools.yang.parser.util.ModuleDependencySort;
import org.opendaylight.yangtools.yang.parser.util.NamedByteArrayInputStream;
}
@Override
- public SchemaContext parseFile(final File yangFile, final File directory) throws IOException,
- YangSyntaxErrorException {
+ public SchemaContext parseFile(final File yangFile, final File directory) throws IOException, YangSyntaxErrorException {
Preconditions.checkState(yangFile.exists(), yangFile + " does not exists");
Preconditions.checkState(directory.exists(), directory + " does not exists");
Preconditions.checkState(directory.isDirectory(), directory + " is not a directory");
@Override
public SchemaContext parseFiles(final Collection<File> yangFiles, final SchemaContext context) throws IOException,
- YangSyntaxErrorException {
+ YangSyntaxErrorException {
if (yangFiles == null) {
return resolveSchemaContext(Collections.<Module> emptySet());
}
}
@Override
- public SchemaContext parseSources(final Collection<ByteSource> sources) throws IOException,
- YangSyntaxErrorException {
- Collection<Module> unsorted = parseYangModelSources(sources).values();
- Set<Module> sorted = new LinkedHashSet<>(
- ModuleDependencySort.sort(unsorted.toArray(new Module[unsorted.size()])));
- return resolveSchemaContext(sorted);
+ public SchemaContext parseSources(final Collection<ByteSource> sources) throws IOException,YangSyntaxErrorException {
+ return assembleContext(parseYangModelSources(sources).values());
}
@Override
return resolveSchemaContext(result);
}
- private LinkedHashMap<String, TreeMap<Date, ModuleBuilder>> resolveModulesWithImports(List<ModuleBuilder> sorted,
- SchemaContext context) {
+ private static LinkedHashMap<String, TreeMap<Date, ModuleBuilder>> resolveModulesWithImports(final List<ModuleBuilder> sorted,
+ final SchemaContext context) {
final LinkedHashMap<String, TreeMap<Date, ModuleBuilder>> modules = orderModules(sorted);
for (ModuleBuilder module : sorted) {
if (module != null) {
return new SchemaContextImpl(modules, identifiersToSources);
}
- private Map<ByteSource, Module> parseYangModelSources(final Collection<ByteSource> sources) throws IOException,
- YangSyntaxErrorException {
+ public Collection<Module> buildModules(final Collection<ModuleBuilder> builders) {
+ List<ModuleBuilder> sorted = ModuleDependencySort.sort(builders);
+ Map<String, TreeMap<Date, ModuleBuilder>> modules = resolveModulesWithImports(sorted, null);
+ Map<ModuleBuilder, Module> builderToModule = build(modules);
+
+ return builderToModule.values();
+ }
+
+ public SchemaContext assembleContext(final Collection<Module> modules) {
+ final Set<Module> sorted = new LinkedHashSet<>(
+ ModuleDependencySort.sort(modules.toArray(new Module[modules.size()])));
+ return resolveSchemaContext(sorted);
+ }
+
+ private Map<ByteSource, Module> parseYangModelSources(final Collection<ByteSource> sources) throws IOException, YangSyntaxErrorException {
if (sources == null || sources.isEmpty()) {
return Collections.emptyMap();
}
* @throws YangSyntaxErrorException
*/
// TODO: remove ByteSource result after removing YangModelParser
- private Map<ByteSource, ModuleBuilder> resolveSources(final Collection<ByteSource> streams) throws IOException,
- YangSyntaxErrorException {
+ private Map<ByteSource, ModuleBuilder> resolveSources(final Collection<ByteSource> streams) throws IOException, YangSyntaxErrorException {
Map<ByteSource, ModuleBuilder> builders = parseSourcesToBuilders(streams);
return resolveSubmodules(builders);
}
* topologically sorted modules
* @return modules ordered by name and revision
*/
- private LinkedHashMap<String, TreeMap<Date, ModuleBuilder>> orderModules(final List<ModuleBuilder> modules) {
+ private static LinkedHashMap<String, TreeMap<Date, ModuleBuilder>> orderModules(final List<ModuleBuilder> modules) {
final LinkedHashMap<String, TreeMap<Date, ModuleBuilder>> result = new LinkedHashMap<>();
for (final ModuleBuilder builder : modules) {
if (builder == null) {
}
}
- private Map<ByteSource, ParseTree> parseYangSources(final Collection<ByteSource> sources) throws IOException,
- YangSyntaxErrorException {
+ private Map<ByteSource, ParseTree> parseYangSources(final Collection<ByteSource> sources) throws IOException, YangSyntaxErrorException {
final Map<ByteSource, ParseTree> trees = new HashMap<>();
for (ByteSource source : sources) {
- trees.put(source, parseYangSource(source));
+ try (InputStream stream = source.openStream()) {
+ trees.put(source, parseYangSource(stream));
+ }
}
return trees;
}
- private YangContext parseYangSource(final ByteSource source) throws IOException, YangSyntaxErrorException {
- try (InputStream stream = source.openStream()) {
- final ANTLRInputStream input = new ANTLRInputStream(stream);
- final YangLexer lexer = new YangLexer(input);
- final CommonTokenStream tokens = new CommonTokenStream(lexer);
- final YangParser parser = new YangParser(tokens);
- parser.removeErrorListeners();
+ public static YangContext parseYangSource(final InputStream stream) throws IOException, YangSyntaxErrorException {
+ final YangLexer lexer = new YangLexer(new ANTLRInputStream(stream));
+ final CommonTokenStream tokens = new CommonTokenStream(lexer);
+ final YangParser parser = new YangParser(tokens);
+ parser.removeErrorListeners();
- final YangErrorListener errorListener = new YangErrorListener();
- parser.addErrorListener(errorListener);
+ final YangErrorListener errorListener = new YangErrorListener();
+ parser.addErrorListener(errorListener);
- final YangContext result = parser.yang();
- errorListener.validate();
+ final YangContext result = parser.yang();
+ errorListener.validate();
- return result;
- }
+ return result;
}
/**
private void setCorrectAugmentTargetPath(final Map<String, TreeMap<Date, ModuleBuilder>> modules,
final AugmentationSchemaBuilder augment) {
ModuleBuilder module = BuilderUtils.getParentModule(augment);
- Iterable<QName> oldPath = augment.getTargetPath().getPathFromRoot();
- List<QName> newPath = new ArrayList<>();
+ final SchemaPath newSchemaPath;
Builder parent = augment.getParent();
if (parent instanceof UsesNodeBuilder) {
DataNodeContainerBuilder usesParent = ((UsesNodeBuilder) parent).getParent();
- newPath.addAll(usesParent.getPath().getPath());
QName baseQName = usesParent.getQName();
final QNameModule qnm;
prefix = baseQName.getPrefix();
}
- for (QName qn : oldPath) {
- newPath.add(QName.create(qnm, prefix, qn.getLocalName()));
+ SchemaPath s = usesParent.getPath();
+ for (QName qn : augment.getTargetPath().getPathFromRoot()) {
+ s = s.createChild(QName.create(qnm, prefix, qn.getLocalName()));
}
+
+ newSchemaPath = s;
} else {
- for (QName qn : oldPath) {
+ final List<QName> newPath = new ArrayList<>();
+
+ for (QName qn : augment.getTargetPath().getPathFromRoot()) {
QNameModule qnm = module.getQNameModule();
String localPrefix = qn.getPrefix();
if (localPrefix != null && !localPrefix.isEmpty()) {
}
qnm = currentModule.getQNameModule();
}
- newPath.add(new QName(qnm.getNamespace(), qnm.getRevision(), localPrefix, qn.getLocalName()));
+ newPath.add(QName.create(qnm, localPrefix, qn.getLocalName()));
}
+
+ /*
+ * FIXME: this method of SchemaPath construction is highly ineffective.
+ * It would be great if we could actually dive into the context,
+ * find the actual target node and reuse its SchemaPath. Can we
+ * do that?
+ */
+ newSchemaPath = SchemaPath.create(newPath, true);
}
- augment.setTargetNodeSchemaPath(SchemaPath.create(newPath, true));
+ augment.setTargetNodeSchemaPath(newSchemaPath);
for (DataSchemaNodeBuilder childNode : augment.getChildNodeBuilders()) {
correctPathForAugmentNodes(childNode, augment.getTargetNodeSchemaPath());
if (mb != null) {
List<AugmentationSchemaBuilder> augments = mb.getAllAugments();
checkAugmentMandatoryNodes(augments);
- Collections.sort(augments, Comparators.AUGMENT_COMP);
+ Collections.sort(augments, Comparators.AUGMENT_BUILDER_COMP);
for (AugmentationSchemaBuilder augment : augments) {
if (!(augment.isResolved())) {
boolean resolved = resolveAugment(augment, mb, modules);
}
}
- private void resolveIdentity(final Map<String, TreeMap<Date, ModuleBuilder>> modules, ModuleBuilder module,
+ private void resolveIdentity(final Map<String, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder module,
final IdentitySchemaNodeBuilder identity) {
final String baseIdentityName = identity.getBaseIdentityName();
if (baseIdentityName != null) {
DataNodeContainerBuilder parent = usesNode.getParent();
ModuleBuilder module = BuilderUtils.getParentModule(parent);
GroupingBuilder target = GroupingUtils.getTargetGroupingFromModules(usesNode, modules, module);
- if (target == null) {
- resolveUsesWithContext(usesNode);
- usesNode.setResolved(true);
- for (AugmentationSchemaBuilder augment : usesNode.getAugmentations()) {
- resolveUsesAugment(augment, module, modules);
- }
- } else {
- parent.getChildNodeBuilders().addAll(target.instantiateChildNodes(parent));
- parent.getTypeDefinitionBuilders().addAll(target.instantiateTypedefs(parent));
- parent.getGroupingBuilders().addAll(target.instantiateGroupings(parent));
- parent.getUnknownNodes().addAll(target.instantiateUnknownNodes(parent));
- usesNode.setResolved(true);
- for (AugmentationSchemaBuilder augment : usesNode.getAugmentations()) {
- resolveUsesAugment(augment, module, modules);
- }
+
+ int index = nodeAfterUsesIndex(usesNode);
+ List<DataSchemaNodeBuilder> targetNodes = target.instantiateChildNodes(parent);
+ for (DataSchemaNodeBuilder targetNode : targetNodes) {
+ parent.addChildNode(index++, targetNode);
+ }
+ parent.getTypeDefinitionBuilders().addAll(target.instantiateTypedefs(parent));
+ parent.getGroupingBuilders().addAll(target.instantiateGroupings(parent));
+ parent.getUnknownNodes().addAll(target.instantiateUnknownNodes(parent));
+ usesNode.setResolved(true);
+ for (AugmentationSchemaBuilder augment : usesNode.getAugmentations()) {
+ resolveUsesAugment(augment, module, modules);
}
+
GroupingUtils.performRefine(usesNode);
}
}
- /**
- * Copy target grouping child nodes to current location with new namespace.
- *
- * @param usesNode
- * uses node to resolve
- */
- private void resolveUsesWithContext(final UsesNodeBuilder usesNode) {
- final int line = usesNode.getLine();
+ private int nodeAfterUsesIndex(final UsesNodeBuilder usesNode) {
DataNodeContainerBuilder parent = usesNode.getParent();
- ModuleBuilder module = BuilderUtils.getParentModule(parent);
- SchemaPath parentPath;
-
- final QName parentQName;
- if (parent instanceof AugmentationSchemaBuilder || parent instanceof ModuleBuilder) {
- parentQName = QName.create(module.getQNameModule(), module.getPrefix(), "dummy");
- if (parent instanceof AugmentationSchemaBuilder) {
- parentPath = ((AugmentationSchemaBuilder) parent).getTargetNodeSchemaPath();
- } else {
- parentPath = parent.getPath();
- }
- } else {
- parentQName = parent.getQName();
- parentPath = parent.getPath();
- }
+ int usesLine = usesNode.getLine();
- GroupingDefinition gd = usesNode.getGroupingDefinition();
-
- Set<DataSchemaNodeBuilder> childNodes = wrapChildNodes(module.getModuleName(), line, gd.getChildNodes(),
- parentPath, parentQName);
- parent.getChildNodeBuilders().addAll(childNodes);
- for (DataSchemaNodeBuilder childNode : childNodes) {
- setNodeAddedByUses(childNode);
+ List<DataSchemaNodeBuilder> childNodes = parent.getChildNodeBuilders();
+ if (childNodes.isEmpty()) {
+ return 0;
}
- Set<TypeDefinitionBuilder> typedefs = wrapTypedefs(module.getModuleName(), line, gd, parentPath, parentQName);
- parent.getTypeDefinitionBuilders().addAll(typedefs);
- for (TypeDefinitionBuilder typedef : typedefs) {
- setNodeAddedByUses(typedef);
+ DataSchemaNodeBuilder nextNodeAfterUses = null;
+ for (DataSchemaNodeBuilder childNode : childNodes) {
+ if (!(childNode.isAddedByUses()) && !(childNode.isAugmenting())) {
+ if (childNode.getLine() > usesLine) {
+ nextNodeAfterUses = childNode;
+ break;
+ }
+ }
}
- Set<GroupingBuilder> groupings = wrapGroupings(module.getModuleName(), line, usesNode.getGroupingDefinition()
- .getGroupings(), parentPath, parentQName);
- parent.getGroupingBuilders().addAll(groupings);
- for (GroupingBuilder gb : groupings) {
- setNodeAddedByUses(gb);
+ // uses is declared after child nodes
+ if (nextNodeAfterUses == null) {
+ return childNodes.size();
}
- List<UnknownSchemaNodeBuilderImpl> unknownNodes = wrapUnknownNodes(module.getModuleName(), line,
- gd.getUnknownSchemaNodes(), parentPath, parentQName);
- parent.getUnknownNodes().addAll(unknownNodes);
- for (UnknownSchemaNodeBuilder un : unknownNodes) {
- un.setAddedByUses(true);
- }
+ return parent.getChildNodeBuilders().indexOf(nextNodeAfterUses);
}
/**
for (UnknownSchemaNodeBuilder usnb : module.getAllUnknownNodes()) {
QName nodeType = usnb.getNodeType();
ModuleBuilder dependentModuleBuilder = BuilderUtils.getModuleByPrefix(module, nodeType.getPrefix());
+ if (dependentModuleBuilder == null) {
+ LOG.warn(
+ "Error in module {} at line {}: Failed to resolve node {}: no such extension definition found.",
+ module.getName(), usnb.getLine(), usnb);
+ continue;
+ }
ExtensionBuilder extBuilder = findExtBuilder(nodeType.getLocalName(),
dependentModuleBuilder.getAddedExtensions());
if (extBuilder == null) {
usnb.setExtensionDefinition(extDef);
}
} else {
- usnb.setNodeType(new QName(extBuilder.getQName().getNamespace(), extBuilder.getQName().getRevision(),
+ usnb.setNodeType(QName.create(extBuilder.getQName().getModule(),
nodeType.getPrefix(), extBuilder.getQName().getLocalName()));
usnb.setExtensionBuilder(extBuilder);
}
}
dev.setTargetPath(((SchemaNodeBuilder) currentParent).getPath());
}
-
}