2 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.controller.yang.model.parser.impl;
11 import java.io.FileInputStream;
12 import java.io.FileNotFoundException;
13 import java.io.IOException;
14 import java.io.InputStream;
15 import java.util.ArrayList;
16 import java.util.Calendar;
17 import java.util.Date;
18 import java.util.HashMap;
19 import java.util.HashSet;
20 import java.util.List;
23 import java.util.TreeMap;
25 import org.antlr.v4.runtime.ANTLRInputStream;
26 import org.antlr.v4.runtime.CommonTokenStream;
27 import org.antlr.v4.runtime.tree.ParseTree;
28 import org.antlr.v4.runtime.tree.ParseTreeWalker;
29 import org.opendaylight.controller.antlrv4.code.gen.YangLexer;
30 import org.opendaylight.controller.antlrv4.code.gen.YangParser;
31 import org.opendaylight.controller.yang.common.QName;
32 import org.opendaylight.controller.yang.model.api.AugmentationSchema;
33 import org.opendaylight.controller.yang.model.api.DataSchemaNode;
34 import org.opendaylight.controller.yang.model.api.ExtensionDefinition;
35 import org.opendaylight.controller.yang.model.api.Module;
36 import org.opendaylight.controller.yang.model.api.ModuleImport;
37 import org.opendaylight.controller.yang.model.api.NotificationDefinition;
38 import org.opendaylight.controller.yang.model.api.RpcDefinition;
39 import org.opendaylight.controller.yang.model.api.SchemaContext;
40 import org.opendaylight.controller.yang.model.api.SchemaPath;
41 import org.opendaylight.controller.yang.model.api.TypeDefinition;
42 import org.opendaylight.controller.yang.model.api.type.BinaryTypeDefinition;
43 import org.opendaylight.controller.yang.model.api.type.DecimalTypeDefinition;
44 import org.opendaylight.controller.yang.model.api.type.IntegerTypeDefinition;
45 import org.opendaylight.controller.yang.model.api.type.LengthConstraint;
46 import org.opendaylight.controller.yang.model.api.type.PatternConstraint;
47 import org.opendaylight.controller.yang.model.api.type.RangeConstraint;
48 import org.opendaylight.controller.yang.model.api.type.StringTypeDefinition;
49 import org.opendaylight.controller.yang.model.parser.api.YangModelParser;
50 import org.opendaylight.controller.yang.model.parser.builder.api.AugmentationSchemaBuilder;
51 import org.opendaylight.controller.yang.model.parser.builder.api.AugmentationTargetBuilder;
52 import org.opendaylight.controller.yang.model.parser.builder.api.ChildNodeBuilder;
53 import org.opendaylight.controller.yang.model.parser.builder.api.DataSchemaNodeBuilder;
54 import org.opendaylight.controller.yang.model.parser.builder.api.TypeAwareBuilder;
55 import org.opendaylight.controller.yang.model.parser.builder.api.TypeDefinitionBuilder;
56 import org.opendaylight.controller.yang.model.parser.builder.impl.IdentitySchemaNodeBuilder;
57 import org.opendaylight.controller.yang.model.parser.builder.impl.ModuleBuilder;
58 import org.opendaylight.controller.yang.model.parser.builder.impl.TypedefBuilder;
59 import org.opendaylight.controller.yang.model.parser.builder.impl.UnionTypeBuilder;
60 import org.opendaylight.controller.yang.model.parser.util.TypeConstraints;
61 import org.opendaylight.controller.yang.model.parser.util.YangParseException;
62 import org.opendaylight.controller.yang.model.util.ExtendedType;
63 import org.opendaylight.controller.yang.model.util.UnknownType;
64 import org.slf4j.Logger;
65 import org.slf4j.LoggerFactory;
67 public class YangModelParserImpl implements YangModelParser {
69 private static final Logger logger = LoggerFactory
70 .getLogger(YangModelParserImpl.class);
73 public Module parseYangModel(final String yangFile) {
74 final Map<String, TreeMap<Date, ModuleBuilder>> modules = resolveModuleBuildersFromStreams(yangFile);
75 final Set<Module> result = build(modules);
76 return result.iterator().next();
80 public Set<Module> parseYangModels(final String... yangFiles) {
81 final Map<String, TreeMap<Date, ModuleBuilder>> modules = resolveModuleBuildersFromStreams(yangFiles);
82 return build(modules);
86 public Set<Module> parseYangModelsFromStreams(
87 final InputStream... yangModelStreams) {
88 final Map<String, TreeMap<Date, ModuleBuilder>> modules = resolveModuleBuildersFromStreams(yangModelStreams);
89 return build(modules);
93 public SchemaContext resolveSchemaContext(final Set<Module> modules) {
94 return new SchemaContextImpl(modules);
97 private Map<String, TreeMap<Date, ModuleBuilder>> resolveModuleBuildersFromStreams(
98 String... yangFiles) {
99 InputStream[] streams = new InputStream[yangFiles.length];
100 FileInputStream inStream = null;
101 for (int i = 0; i < yangFiles.length; i++) {
102 final String yangFileName = yangFiles[i];
103 final File yangFile = new File(yangFileName);
105 inStream = new FileInputStream(yangFile);
106 } catch (FileNotFoundException e) {
107 logger.warn("Exception while reading yang stream: " + inStream,
110 streams[i] = inStream;
112 return resolveModuleBuildersFromStreams(streams);
115 private Map<String, TreeMap<Date, ModuleBuilder>> resolveModuleBuildersFromStreams(
116 InputStream... yangFiles) {
117 final Map<String, TreeMap<Date, ModuleBuilder>> modules = new HashMap<String, TreeMap<Date, ModuleBuilder>>();
118 final ParseTreeWalker walker = new ParseTreeWalker();
119 final List<ParseTree> trees = parseStreams(yangFiles);
120 final ModuleBuilder[] builders = new ModuleBuilder[trees.size()];
123 // if validation fails with any file, do not continue and throw
\r
125 for (int i = 0; i < trees.size(); i++) {
\r
127 final YangModelValidationListener yangModelParser = new YangModelValidationListener();
\r
128 walker.walk(yangModelParser, trees.get(i));
\r
129 } catch (IllegalStateException e) {
\r
130 // wrap exception to add information about which file failed
\r
131 throw new YangValidationException(
\r
132 "Yang validation failed for file" + yangFiles[i], e);
\r
137 YangModelParserListenerImpl yangModelParser = null;
138 for (int i = 0; i < trees.size(); i++) {
139 yangModelParser = new YangModelParserListenerImpl();
140 walker.walk(yangModelParser, trees.get(i));
141 builders[i] = yangModelParser.getModuleBuilder();
144 for (ModuleBuilder builder : builders) {
145 final String builderName = builder.getName();
146 Date builderRevision = builder.getRevision();
147 if (builderRevision == null) {
148 builderRevision = createEpochTime();
150 TreeMap<Date, ModuleBuilder> builderByRevision = modules
152 if (builderByRevision == null) {
153 builderByRevision = new TreeMap<Date, ModuleBuilder>();
155 builderByRevision.put(builderRevision, builder);
156 modules.put(builderName, builderByRevision);
161 private List<ParseTree> parseStreams(InputStream... yangStreams) {
162 final List<ParseTree> trees = new ArrayList<ParseTree>();
163 for (InputStream yangStream : yangStreams) {
164 trees.add(parseStream(yangStream));
169 private ParseTree parseStream(InputStream yangStream) {
170 ParseTree result = null;
172 final ANTLRInputStream input = new ANTLRInputStream(yangStream);
173 final YangLexer lexer = new YangLexer(input);
174 final CommonTokenStream tokens = new CommonTokenStream(lexer);
175 final YangParser parser = new YangParser(tokens);
176 result = parser.yang();
177 } catch (IOException e) {
178 logger.warn("Exception while reading yang file: " + yangStream, e);
183 private Set<Module> build(Map<String, TreeMap<Date, ModuleBuilder>> modules) {
185 for (Map.Entry<String, TreeMap<Date, ModuleBuilder>> entry : modules
187 for (Map.Entry<Date, ModuleBuilder> childEntry : entry.getValue()
189 ModuleBuilder moduleBuilder = childEntry.getValue();
190 validateModule(modules, moduleBuilder);
195 final Set<Module> result = new HashSet<Module>();
196 for (Map.Entry<String, TreeMap<Date, ModuleBuilder>> entry : modules
198 final Map<Date, Module> modulesByRevision = new HashMap<Date, Module>();
199 for (Map.Entry<Date, ModuleBuilder> childEntry : entry.getValue()
201 ModuleBuilder moduleBuilder = childEntry.getValue();
202 Module module = moduleBuilder.build();
203 modulesByRevision.put(childEntry.getKey(), module);
210 private void validateModule(
211 Map<String, TreeMap<Date, ModuleBuilder>> modules,
212 ModuleBuilder builder) {
213 resolveDirtyNodes(modules, builder);
214 resolveAugments(modules, builder);
215 resolveIdentities(modules, builder);
219 * Search for dirty nodes (node which contains UnknownType) and resolve
223 * all available modules
227 private void resolveDirtyNodes(
228 Map<String, TreeMap<Date, ModuleBuilder>> modules,
229 ModuleBuilder module) {
230 final Map<List<String>, TypeAwareBuilder> dirtyNodes = module
232 if (!dirtyNodes.isEmpty()) {
233 for (Map.Entry<List<String>, TypeAwareBuilder> entry : dirtyNodes
236 TypeAwareBuilder typeToResolve = entry.getValue();
237 if (typeToResolve instanceof UnionTypeBuilder) {
238 UnionTypeBuilder union = (UnionTypeBuilder) typeToResolve;
239 List<TypeDefinition<?>> unionTypes = union.getTypes();
240 List<UnknownType> toRemove = new ArrayList<UnknownType>();
241 for (TypeDefinition<?> td : unionTypes) {
242 if (td instanceof UnknownType) {
243 UnknownType unknownType = (UnknownType) td;
244 TypeDefinitionBuilder resolvedType = findTargetTypeUnion(
245 typeToResolve, unknownType, modules, module);
246 union.setType(resolvedType);
247 toRemove.add(unknownType);
250 unionTypes.removeAll(toRemove);
252 TypeDefinitionBuilder resolvedType = findTargetType(
253 typeToResolve, modules, module);
254 typeToResolve.setType(resolvedType);
260 private TypeDefinitionBuilder findTargetType(
261 TypeAwareBuilder typeToResolve,
262 Map<String, TreeMap<Date, ModuleBuilder>> modules,
263 ModuleBuilder builder) {
264 TypeConstraints constraints = new TypeConstraints();
266 TypeDefinitionBuilder targetType = findTypedef(typeToResolve, modules,
268 TypeConstraints tConstraints = findConstraints(typeToResolve,
269 constraints, modules, builder);
270 targetType.setRanges(tConstraints.getRange());
271 targetType.setLengths(tConstraints.getLength());
272 targetType.setPatterns(tConstraints.getPatterns());
273 targetType.setFractionDigits(tConstraints.getFractionDigits());
278 private TypeDefinitionBuilder findTargetTypeUnion(
279 TypeAwareBuilder typeToResolve, UnknownType unknownType,
280 Map<String, TreeMap<Date, ModuleBuilder>> modules,
281 ModuleBuilder builder) {
282 TypeConstraints constraints = new TypeConstraints();
284 TypeDefinitionBuilder targetType = findTypedefUnion(typeToResolve,
285 unknownType, modules, builder);
286 TypeConstraints tConstraints = findConstraints(typeToResolve,
287 constraints, modules, builder);
288 targetType.setRanges(tConstraints.getRange());
289 targetType.setLengths(tConstraints.getLength());
290 targetType.setPatterns(tConstraints.getPatterns());
291 targetType.setFractionDigits(tConstraints.getFractionDigits());
296 private TypeDefinitionBuilder findTypedef(TypeAwareBuilder typeToResolve,
297 Map<String, TreeMap<Date, ModuleBuilder>> modules,
298 ModuleBuilder builder) {
300 TypeDefinition<?> baseTypeToResolve = typeToResolve.getType();
301 if (baseTypeToResolve != null
302 && !(baseTypeToResolve instanceof UnknownType)) {
303 return (TypeDefinitionBuilder) typeToResolve;
306 UnknownType unknownType = (UnknownType) typeToResolve.getType();
308 QName unknownTypeQName = unknownType.getQName();
309 String unknownTypeName = unknownTypeQName.getLocalName();
310 String unknownTypePrefix = unknownTypeQName.getPrefix();
312 // search for module which contains referenced typedef
313 ModuleBuilder dependentModule = findDependentModule(modules, builder,
315 TypeDefinitionBuilder lookedUpBuilder = findTypedefBuilder(
316 dependentModule.getModuleTypedefs(), unknownTypeName);
318 TypeDefinitionBuilder lookedUpBuilderCopy = copyTypedefBuilder(
319 lookedUpBuilder, typeToResolve instanceof TypeDefinitionBuilder);
320 TypeDefinitionBuilder resolvedCopy = resolveCopiedBuilder(
321 lookedUpBuilderCopy, modules, dependentModule);
325 private TypeDefinitionBuilder findTypedefUnion(
326 TypeAwareBuilder typeToResolve, UnknownType unknownType,
327 Map<String, TreeMap<Date, ModuleBuilder>> modules,
328 ModuleBuilder builder) {
330 TypeDefinition<?> baseTypeToResolve = typeToResolve.getType();
331 if (baseTypeToResolve != null
332 && !(baseTypeToResolve instanceof UnknownType)) {
333 return (TypeDefinitionBuilder) typeToResolve;
336 QName unknownTypeQName = unknownType.getQName();
337 String unknownTypeName = unknownTypeQName.getLocalName();
338 String unknownTypePrefix = unknownTypeQName.getPrefix();
340 // search for module which contains referenced typedef
341 ModuleBuilder dependentModule = findDependentModule(modules, builder,
343 TypeDefinitionBuilder lookedUpBuilder = findTypedefBuilder(
344 dependentModule.getModuleTypedefs(), unknownTypeName);
346 TypeDefinitionBuilder lookedUpBuilderCopy = copyTypedefBuilder(
347 lookedUpBuilder, typeToResolve instanceof TypeDefinitionBuilder);
348 TypeDefinitionBuilder resolvedCopy = resolveCopiedBuilder(
349 lookedUpBuilderCopy, modules, dependentModule);
353 private TypeDefinitionBuilder copyTypedefBuilder(TypeDefinitionBuilder old,
354 boolean seekByTypedefBuilder) {
355 if (old instanceof UnionTypeBuilder) {
356 UnionTypeBuilder oldUnion = (UnionTypeBuilder) old;
357 UnionTypeBuilder newUnion = new UnionTypeBuilder();
358 for (TypeDefinition<?> td : oldUnion.getTypes()) {
359 newUnion.setType(td);
361 for (TypeDefinitionBuilder tdb : oldUnion.getTypedefs()) {
362 newUnion.setType(copyTypedefBuilder(tdb, true));
367 QName oldQName = old.getQName();
368 QName newQName = new QName(oldQName.getNamespace(),
369 oldQName.getRevision(), oldQName.getPrefix(),
370 oldQName.getLocalName());
371 TypeDefinitionBuilder tdb = new TypedefBuilder(newQName);
373 tdb.setRanges(old.getRanges());
374 tdb.setLengths(old.getLengths());
375 tdb.setPatterns(old.getPatterns());
377 TypeDefinition<?> oldType = old.getType();
378 if (oldType == null) {
379 tdb.setType(old.getTypedef());
381 tdb.setType(oldType);
384 if (!seekByTypedefBuilder) {
385 tdb.setDescription(old.getDescription());
386 tdb.setReference(old.getReference());
387 tdb.setStatus(old.getStatus());
388 tdb.setDefaultValue(old.getDefaultValue());
389 tdb.setUnits(old.getUnits());
394 private TypeDefinitionBuilder resolveCopiedBuilder(
395 TypeDefinitionBuilder copied,
396 Map<String, TreeMap<Date, ModuleBuilder>> modules,
397 ModuleBuilder builder) {
399 if (copied instanceof UnionTypeBuilder) {
400 UnionTypeBuilder union = (UnionTypeBuilder) copied;
401 List<TypeDefinition<?>> unionTypes = union.getTypes();
402 List<UnknownType> toRemove = new ArrayList<UnknownType>();
403 for (TypeDefinition<?> td : unionTypes) {
404 if (td instanceof UnknownType) {
405 UnknownType unknownType = (UnknownType) td;
406 TypeDefinitionBuilder resolvedType = findTargetTypeUnion(
407 union, unknownType, modules, builder);
408 union.setType(resolvedType);
409 toRemove.add(unknownType);
412 unionTypes.removeAll(toRemove);
417 TypeDefinition<?> base = copied.getType();
418 TypeDefinitionBuilder baseTdb = copied.getTypedef();
419 if (base != null && !(base instanceof UnknownType)) {
421 } else if (base instanceof UnknownType) {
422 UnknownType unknownType = (UnknownType) base;
423 QName unknownTypeQName = unknownType.getQName();
424 String unknownTypePrefix = unknownTypeQName.getPrefix();
425 ModuleBuilder dependentModule = findDependentModule(modules,
426 builder, unknownTypePrefix);
427 TypeDefinitionBuilder unknownTypeBuilder = findTypedef(copied,
428 modules, dependentModule);
429 copied.setType(unknownTypeBuilder);
431 } else if (base == null && baseTdb != null) {
432 // make a copy of baseTypeDef and call again
433 TypeDefinitionBuilder baseTdbCopy = copyTypedefBuilder(baseTdb,
435 TypeDefinitionBuilder baseTdbCopyResolved = resolveCopiedBuilder(
436 baseTdbCopy, modules, builder);
437 copied.setType(baseTdbCopyResolved);
440 throw new IllegalStateException(
441 "TypeDefinitionBuilder in unexpected state");
445 private TypeDefinitionBuilder findTypedef(QName unknownTypeQName,
446 Map<String, TreeMap<Date, ModuleBuilder>> modules,
447 ModuleBuilder builder) {
449 String unknownTypeName = unknownTypeQName.getLocalName();
450 String unknownTypePrefix = unknownTypeQName.getPrefix();
452 // search for module which contains referenced typedef
453 ModuleBuilder dependentModule = findDependentModule(modules, builder,
456 TypeDefinitionBuilder lookedUpBuilder = findTypedefBuilder(
457 dependentModule.getModuleTypedefs(), unknownTypeName);
459 TypeDefinitionBuilder copied = copyTypedefBuilder(lookedUpBuilder, true);
463 private TypeConstraints findConstraints(TypeAwareBuilder typeToResolve,
464 TypeConstraints constraints,
465 Map<String, TreeMap<Date, ModuleBuilder>> modules,
466 ModuleBuilder builder) {
468 // union type cannot be restricted
469 if (typeToResolve instanceof UnionTypeBuilder) {
473 // if referenced type is UnknownType again, search recursively with
474 // current constraints
475 TypeDefinition<?> referencedType = typeToResolve.getType();
476 if (referencedType == null) {
477 TypeDefinitionBuilder tdb = (TypeDefinitionBuilder) typeToResolve;
478 final List<RangeConstraint> ranges = tdb.getRanges();
479 constraints.addRanges(ranges);
480 final List<LengthConstraint> lengths = tdb.getLengths();
481 constraints.addLengths(lengths);
482 final List<PatternConstraint> patterns = tdb.getPatterns();
483 constraints.addPatterns(patterns);
484 final Integer fractionDigits = tdb.getFractionDigits();
485 constraints.setFractionDigits(fractionDigits);
487 } else if (referencedType instanceof ExtendedType) {
488 ExtendedType ext = (ExtendedType) referencedType;
489 final List<RangeConstraint> ranges = ext.getRanges();
490 constraints.addRanges(ranges);
491 final List<LengthConstraint> lengths = ext.getLengths();
492 constraints.addLengths(lengths);
493 final List<PatternConstraint> patterns = ext.getPatterns();
494 constraints.addPatterns(patterns);
495 final Integer fractionDigits = ext.getFractionDigits();
496 constraints.setFractionDigits(fractionDigits);
497 return findConstraints(
498 findTypedef(ext.getQName(), modules, builder), constraints,
500 } else if (referencedType instanceof UnknownType) {
501 UnknownType unknown = (UnknownType) referencedType;
503 final List<RangeConstraint> ranges = unknown.getRangeStatements();
504 constraints.addRanges(ranges);
505 final List<LengthConstraint> lengths = unknown
506 .getLengthStatements();
507 constraints.addLengths(lengths);
508 final List<PatternConstraint> patterns = unknown.getPatterns();
509 constraints.addPatterns(patterns);
510 final Integer fractionDigits = unknown.getFractionDigits();
511 constraints.setFractionDigits(fractionDigits);
513 String unknownTypePrefix = unknown.getQName().getPrefix();
514 if (unknownTypePrefix == null || "".equals(unknownTypePrefix)) {
515 unknownTypePrefix = builder.getPrefix();
517 ModuleBuilder dependentModule = findDependentModule(modules,
518 builder, unknown.getQName().getPrefix());
519 TypeDefinitionBuilder unknownTypeBuilder = findTypedef(
520 unknown.getQName(), modules, builder);
521 return findConstraints(unknownTypeBuilder, constraints, modules,
524 // HANDLE BASE YANG TYPE
525 mergeConstraints(referencedType, constraints);
532 * Go through all typedef statements from given module and search for one
536 * typedef statements to search
538 * name of searched typedef
539 * @return typedef with name equals to given name
541 private TypeDefinitionBuilder findTypedefBuilder(
542 Set<TypeDefinitionBuilder> typedefs, String name) {
543 TypeDefinitionBuilder result = null;
544 for (TypeDefinitionBuilder td : typedefs) {
545 if (td.getQName().getLocalName().equals(name)) {
550 if (result == null) {
551 throw new YangParseException(
552 "Target module does not contain typedef '" + name + "'.");
558 * Pull restriction from referenced type and add them to given constraints
560 * @param referencedType
563 private void mergeConstraints(TypeDefinition<?> referencedType,
564 TypeConstraints constraints) {
566 if (referencedType instanceof DecimalTypeDefinition) {
567 constraints.addRanges(((DecimalTypeDefinition) referencedType)
568 .getRangeStatements());
570 .setFractionDigits(((DecimalTypeDefinition) referencedType)
571 .getFractionDigits());
572 } else if (referencedType instanceof IntegerTypeDefinition) {
573 constraints.addRanges(((IntegerTypeDefinition) referencedType)
574 .getRangeStatements());
575 } else if (referencedType instanceof StringTypeDefinition) {
576 constraints.addPatterns(((StringTypeDefinition) referencedType)
578 constraints.addLengths(((StringTypeDefinition) referencedType)
579 .getLengthStatements());
580 } else if (referencedType instanceof BinaryTypeDefinition) {
581 constraints.addLengths(((BinaryTypeDefinition) referencedType)
582 .getLengthConstraints());
587 * Go through all augmentation definitions and resolve them. This means find
588 * referenced node and add child nodes to it.
591 * all available modules
595 private void resolveAugments(
596 Map<String, TreeMap<Date, ModuleBuilder>> modules,
597 ModuleBuilder module) {
598 Set<AugmentationSchemaBuilder> augmentBuilders = module
601 Set<AugmentationSchema> augments = new HashSet<AugmentationSchema>();
602 for (AugmentationSchemaBuilder augmentBuilder : augmentBuilders) {
603 SchemaPath augmentTargetSchemaPath = augmentBuilder.getTargetPath();
604 String prefix = null;
605 List<String> augmentTargetPath = new ArrayList<String>();
607 for (QName pathPart : augmentTargetSchemaPath.getPath()) {
608 prefix = pathPart.getPrefix();
609 augmentTargetPath.add(pathPart.getLocalName());
611 ModuleBuilder dependentModule = findDependentModule(modules,
613 augmentTargetPath.add(0, dependentModule.getName());
615 AugmentationTargetBuilder augmentTarget = (AugmentationTargetBuilder) dependentModule
616 .getNode(augmentTargetPath);
617 AugmentationSchema result = augmentBuilder.build();
618 augmentTarget.addAugmentation(result);
619 fillAugmentTarget(augmentBuilder, (ChildNodeBuilder) augmentTarget);
620 augments.add(result);
622 module.setAugmentations(augments);
626 * Add all augment's child nodes to given target.
631 private void fillAugmentTarget(AugmentationSchemaBuilder augment,
632 ChildNodeBuilder target) {
633 for (DataSchemaNodeBuilder builder : augment.getChildNodes()) {
634 builder.setAugmenting(true);
635 target.addChildNode(builder);
640 * Go through identity statements defined in current module and resolve
641 * their 'base' statement if present.
646 * module being resolved
648 private void resolveIdentities(
649 Map<String, TreeMap<Date, ModuleBuilder>> modules,
650 ModuleBuilder module) {
651 Set<IdentitySchemaNodeBuilder> identities = module.getAddedIdentities();
652 for (IdentitySchemaNodeBuilder identity : identities) {
653 String baseIdentityName = identity.getBaseIdentityName();
654 if (baseIdentityName != null) {
655 String baseIdentityPrefix = null;
656 String baseIdentityLocalName = null;
657 if (baseIdentityName.contains(":")) {
658 String[] splitted = baseIdentityName.split(":");
659 baseIdentityPrefix = splitted[0];
660 baseIdentityLocalName = splitted[1];
662 baseIdentityPrefix = module.getPrefix();
663 baseIdentityLocalName = baseIdentityName;
665 ModuleBuilder dependentModule = findDependentModule(modules,
666 module, baseIdentityPrefix);
668 Set<IdentitySchemaNodeBuilder> dependentModuleIdentities = dependentModule
669 .getAddedIdentities();
670 for (IdentitySchemaNodeBuilder idBuilder : dependentModuleIdentities) {
671 if (idBuilder.getQName().getLocalName()
672 .equals(baseIdentityLocalName)) {
673 identity.setBaseIdentity(idBuilder);
681 * Find dependent module based on given prefix
684 * all available modules
688 * target module prefix
691 private ModuleBuilder findDependentModule(
692 Map<String, TreeMap<Date, ModuleBuilder>> modules,
693 ModuleBuilder module, String prefix) {
694 ModuleBuilder dependentModule = null;
695 Date dependentModuleRevision = null;
697 if (prefix.equals(module.getPrefix())) {
698 dependentModule = module;
700 ModuleImport dependentModuleImport = getModuleImport(module, prefix);
701 if (dependentModuleImport == null) {
702 throw new YangParseException("No import found with prefix '"
703 + prefix + "' in module " + module.getName() + "'.");
705 String dependentModuleName = dependentModuleImport.getModuleName();
706 dependentModuleRevision = dependentModuleImport.getRevision();
708 TreeMap<Date, ModuleBuilder> moduleBuildersByRevision = modules
709 .get(dependentModuleName);
710 if (dependentModuleRevision == null) {
711 dependentModule = moduleBuildersByRevision.lastEntry()
714 dependentModule = moduleBuildersByRevision
715 .get(dependentModuleRevision);
719 if (dependentModule == null) {
720 throw new YangParseException(
721 "Failed to find dependent module with prefix '" + prefix
722 + "' and revision '" + dependentModuleRevision
725 return dependentModule;
729 * Get module import referenced by given prefix.
734 * prefix associated with import
735 * @return ModuleImport based on given prefix
737 private ModuleImport getModuleImport(ModuleBuilder builder, String prefix) {
738 ModuleImport moduleImport = null;
739 for (ModuleImport mi : builder.getModuleImports()) {
740 if (mi.getPrefix().equals(prefix)) {
748 private Date createEpochTime() {
749 Calendar calendar = Calendar.getInstance();
750 calendar.setTimeInMillis(0);
751 return calendar.getTime();
754 private static class SchemaContextImpl implements SchemaContext {
755 private final Set<Module> modules;
757 private SchemaContextImpl(Set<Module> modules) {
758 this.modules = modules;
762 public Set<DataSchemaNode> getDataDefinitions() {
763 final Set<DataSchemaNode> dataDefs = new HashSet<DataSchemaNode>();
764 for (Module m : modules) {
765 dataDefs.addAll(m.getChildNodes());
771 public Set<Module> getModules() {
776 public Set<NotificationDefinition> getNotifications() {
777 final Set<NotificationDefinition> notifications = new HashSet<NotificationDefinition>();
778 for (Module m : modules) {
779 notifications.addAll(m.getNotifications());
781 return notifications;
785 public Set<RpcDefinition> getOperations() {
786 final Set<RpcDefinition> rpcs = new HashSet<RpcDefinition>();
787 for (Module m : modules) {
788 rpcs.addAll(m.getRpcs());
794 public Set<ExtensionDefinition> getExtensions() {
795 final Set<ExtensionDefinition> extensions = new HashSet<ExtensionDefinition>();
796 for (Module m : modules) {
797 extensions.addAll(m.getExtensionSchemaNodes());