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.BitsTypeDefinition;
44 import org.opendaylight.controller.yang.model.api.type.BitsTypeDefinition.Bit;
45 import org.opendaylight.controller.yang.model.api.type.DecimalTypeDefinition;
46 import org.opendaylight.controller.yang.model.api.type.IntegerTypeDefinition;
47 import org.opendaylight.controller.yang.model.api.type.LengthConstraint;
48 import org.opendaylight.controller.yang.model.api.type.PatternConstraint;
49 import org.opendaylight.controller.yang.model.api.type.RangeConstraint;
50 import org.opendaylight.controller.yang.model.api.type.StringTypeDefinition;
51 import org.opendaylight.controller.yang.model.parser.api.YangModelParser;
52 import org.opendaylight.controller.yang.model.parser.builder.api.AugmentationSchemaBuilder;
53 import org.opendaylight.controller.yang.model.parser.builder.api.AugmentationTargetBuilder;
54 import org.opendaylight.controller.yang.model.parser.builder.api.ChildNodeBuilder;
55 import org.opendaylight.controller.yang.model.parser.builder.api.DataSchemaNodeBuilder;
56 import org.opendaylight.controller.yang.model.parser.builder.api.TypeAwareBuilder;
57 import org.opendaylight.controller.yang.model.parser.builder.api.TypeDefinitionBuilder;
58 import org.opendaylight.controller.yang.model.parser.builder.impl.IdentitySchemaNodeBuilder;
59 import org.opendaylight.controller.yang.model.parser.builder.impl.ModuleBuilder;
60 import org.opendaylight.controller.yang.model.parser.builder.impl.UnionTypeBuilder;
61 import org.opendaylight.controller.yang.model.util.BaseConstraints;
62 import org.opendaylight.controller.yang.model.util.BinaryType;
63 import org.opendaylight.controller.yang.model.util.BitsType;
64 import org.opendaylight.controller.yang.model.util.StringType;
65 import org.opendaylight.controller.yang.model.util.UnknownType;
66 import org.opendaylight.controller.yang.model.util.YangTypesConverter;
67 import org.slf4j.Logger;
68 import org.slf4j.LoggerFactory;
70 public class YangModelParserImpl implements YangModelParser {
72 private static final Logger logger = LoggerFactory
73 .getLogger(YangModelParserImpl.class);
76 public Module parseYangModel(String yangFile) {
77 final Map<String, TreeMap<Date, ModuleBuilder>> modules = resolveModuleBuildersFromStreams(yangFile);
78 Set<Module> result = build(modules);
79 return result.iterator().next();
83 public Set<Module> parseYangModels(String... yangFiles) {
84 final Map<String, TreeMap<Date, ModuleBuilder>> modules = resolveModuleBuildersFromStreams(yangFiles);
85 Set<Module> result = build(modules);
90 public Set<Module> parseYangModelsFromStreams(
91 InputStream... yangModelStreams) {
92 final Map<String, TreeMap<Date, ModuleBuilder>> modules = resolveModuleBuildersFromStreams(yangModelStreams);
93 Set<Module> result = build(modules);
98 public SchemaContext resolveSchemaContext(Set<Module> modules) {
99 return new SchemaContextImpl(modules);
102 private Map<String, TreeMap<Date, ModuleBuilder>> resolveModuleBuildersFromStreams(
103 String... yangFiles) {
104 InputStream[] streams = new InputStream[yangFiles.length];
105 for (int i = 0; i < yangFiles.length; i++) {
106 final String yangFileName = yangFiles[i];
107 final File yangFile = new File(yangFileName);
108 FileInputStream inStream = null;
110 inStream = new FileInputStream(yangFile);
111 } catch (FileNotFoundException e) {
112 logger.warn("Exception while reading yang stream: " + inStream,
115 streams[i] = inStream;
117 return resolveModuleBuildersFromStreams(streams);
120 private Map<String, TreeMap<Date, ModuleBuilder>> resolveModuleBuildersFromStreams(
121 InputStream... yangFiles) {
122 final Map<String, TreeMap<Date, ModuleBuilder>> modules = new HashMap<String, TreeMap<Date, ModuleBuilder>>();
124 final YangModelParserListenerImpl yangModelParser = new YangModelParserListenerImpl();
125 final ParseTreeWalker walker = new ParseTreeWalker();
127 List<ParseTree> trees = parseStreams(yangFiles);
129 ModuleBuilder[] builders = new ModuleBuilder[trees.size()];
131 for (int i = 0; i < trees.size(); i++) {
132 walker.walk(yangModelParser, trees.get(i));
133 builders[i] = yangModelParser.getModuleBuilder();
136 for (ModuleBuilder builder : builders) {
137 final String builderName = builder.getName();
138 Date builderRevision = builder.getRevision();
139 if (builderRevision == null) {
140 builderRevision = createEpochTime();
142 TreeMap<Date, ModuleBuilder> builderByRevision = modules
144 if (builderByRevision == null) {
145 builderByRevision = new TreeMap<Date, ModuleBuilder>();
147 builderByRevision.put(builderRevision, builder);
148 modules.put(builderName, builderByRevision);
153 private List<ParseTree> parseStreams(InputStream... yangStreams) {
154 List<ParseTree> trees = new ArrayList<ParseTree>();
155 for (InputStream yangStream : yangStreams) {
156 trees.add(parseStream(yangStream));
161 private ParseTree parseStream(InputStream yangStream) {
162 ParseTree result = null;
164 final ANTLRInputStream input = new ANTLRInputStream(yangStream);
165 final YangLexer lexer = new YangLexer(input);
166 final CommonTokenStream tokens = new CommonTokenStream(lexer);
167 final YangParser parser = new YangParser(tokens);
168 result = parser.yang();
169 } catch (IOException e) {
170 logger.warn("Exception while reading yang file: " + yangStream, e);
175 private Set<Module> build(Map<String, TreeMap<Date, ModuleBuilder>> modules) {
177 for (Map.Entry<String, TreeMap<Date, ModuleBuilder>> entry : modules
179 for (Map.Entry<Date, ModuleBuilder> childEntry : entry.getValue()
181 ModuleBuilder moduleBuilder = childEntry.getValue();
182 validateBuilder(modules, moduleBuilder);
186 final Set<Module> result = new HashSet<Module>();
187 for (Map.Entry<String, TreeMap<Date, ModuleBuilder>> entry : modules
189 final Map<Date, Module> modulesByRevision = new HashMap<Date, Module>();
190 for (Map.Entry<Date, ModuleBuilder> childEntry : entry.getValue()
192 ModuleBuilder moduleBuilder = childEntry.getValue();
193 modulesByRevision.put(childEntry.getKey(),
194 moduleBuilder.build());
195 result.add(moduleBuilder.build());
202 private void validateBuilder(
203 Map<String, TreeMap<Date, ModuleBuilder>> modules,
204 ModuleBuilder builder) {
205 resolveTypedefs(modules, builder);
206 resolveAugments(modules, builder);
207 resolveIdentities(modules, builder);
211 * Search for dirty nodes (node which contains UnknownType) and resolve
215 * all available modules
219 private void resolveTypedefs(
220 Map<String, TreeMap<Date, ModuleBuilder>> modules,
221 ModuleBuilder module) {
222 Map<List<String>, TypeAwareBuilder> dirtyNodes = module.getDirtyNodes();
223 if (dirtyNodes.size() == 0) {
226 for (Map.Entry<List<String>, TypeAwareBuilder> entry : dirtyNodes
228 TypeAwareBuilder typeToResolve = entry.getValue();
230 if (typeToResolve instanceof UnionTypeBuilder) {
231 resolveUnionTypeBuilder(modules, module,
232 (UnionTypeBuilder) typeToResolve);
234 UnknownType ut = (UnknownType) typeToResolve.getType();
235 TypeDefinition<?> resolvedType = findTargetType(ut,
237 typeToResolve.setType(resolvedType);
243 private UnionTypeBuilder resolveUnionTypeBuilder(
244 Map<String, TreeMap<Date, ModuleBuilder>> modules,
245 ModuleBuilder builder, UnionTypeBuilder unionTypeBuilderToResolve) {
246 List<TypeDefinition<?>> resolvedTypes = new ArrayList<TypeDefinition<?>>();
247 List<TypeDefinition<?>> typesToRemove = new ArrayList<TypeDefinition<?>>();
249 for (TypeDefinition<?> td : unionTypeBuilderToResolve.getTypes()) {
250 if (td instanceof UnknownType) {
251 TypeDefinition<?> resolvedType = findTargetType(
252 (UnknownType) td, modules, builder);
253 resolvedTypes.add(resolvedType);
254 typesToRemove.add(td);
258 List<TypeDefinition<?>> unionTypeBuilderTypes = unionTypeBuilderToResolve
260 unionTypeBuilderTypes.addAll(resolvedTypes);
261 unionTypeBuilderTypes.removeAll(typesToRemove);
263 return unionTypeBuilderToResolve;
266 private TypeDefinition<?> findTargetType(UnknownType ut,
267 Map<String, TreeMap<Date, ModuleBuilder>> modules,
268 ModuleBuilder builder) {
270 Map<TypeDefinitionBuilder, TypeConstraints> foundedTypeDefinitionBuilder = findTypeDefinitionBuilderWithConstraints(
271 modules, ut, builder);
272 TypeDefinitionBuilder targetType = foundedTypeDefinitionBuilder
273 .entrySet().iterator().next().getKey();
274 TypeConstraints constraints = foundedTypeDefinitionBuilder.entrySet()
275 .iterator().next().getValue();
277 TypeDefinition<?> targetTypeBaseType = targetType.getBaseType();
280 List<RangeConstraint> ranges = ut.getRangeStatements();
281 resolveRanges(ranges, targetType, modules, builder);
283 List<LengthConstraint> lengths = ut.getLengthStatements();
284 resolveLengths(lengths, targetType, modules, builder);
286 List<PatternConstraint> patterns = ut.getPatterns();
288 Integer fractionDigits = ut.getFractionDigits();
290 targetTypeBaseType = mergeConstraints(targetTypeBaseType, constraints, ranges, lengths,
291 patterns, fractionDigits);
293 return targetTypeBaseType;
297 * Merge curent constraints with founded type constraints
299 * @param targetTypeBaseType
304 * @param fractionDigits
306 private TypeDefinition<?> mergeConstraints(TypeDefinition<?> targetTypeBaseType,
307 TypeConstraints constraints, List<RangeConstraint> ranges,
308 List<LengthConstraint> lengths, List<PatternConstraint> patterns,
309 Integer fractionDigits) {
310 String targetTypeBaseTypeName = targetTypeBaseType.getQName()
312 // enumeration, leafref and identityref omitted because they have no
314 if (targetTypeBaseType instanceof DecimalTypeDefinition) {
315 List<RangeConstraint> fullRanges = new ArrayList<RangeConstraint>();
316 fullRanges.addAll(constraints.getRanges());
317 fullRanges.addAll(ranges);
318 Integer fd = fractionDigits == null ? constraints
319 .getFractionDigits() : fractionDigits;
320 targetTypeBaseType = YangTypesConverter
321 .javaTypeForBaseYangDecimal64Type(fullRanges, fd);
322 } else if (targetTypeBaseType instanceof IntegerTypeDefinition) {
323 List<RangeConstraint> fullRanges = new ArrayList<RangeConstraint>();
324 fullRanges.addAll(constraints.getRanges());
325 fullRanges.addAll(ranges);
326 if (targetTypeBaseTypeName.startsWith("int")) {
327 targetTypeBaseType = YangTypesConverter
328 .javaTypeForBaseYangSignedIntegerType(
329 targetTypeBaseTypeName, fullRanges);
331 targetTypeBaseType = YangTypesConverter
332 .javaTypeForBaseYangUnsignedIntegerType(
333 targetTypeBaseTypeName, fullRanges);
335 } else if (targetTypeBaseType instanceof StringTypeDefinition) {
336 List<LengthConstraint> fullLengths = new ArrayList<LengthConstraint>();
337 fullLengths.addAll(constraints.getLengths());
338 fullLengths.addAll(lengths);
339 List<PatternConstraint> fullPatterns = new ArrayList<PatternConstraint>();
340 fullPatterns.addAll(constraints.getPatterns());
341 fullPatterns.addAll(patterns);
342 targetTypeBaseType = new StringType(fullLengths, fullPatterns);
343 } else if (targetTypeBaseType instanceof BitsTypeDefinition) {
344 BitsTypeDefinition bitsType = (BitsTypeDefinition) targetTypeBaseType;
345 List<Bit> bits = bitsType.getBits();
346 targetTypeBaseType = new BitsType(bits);
347 } else if (targetTypeBaseType instanceof BinaryTypeDefinition) {
348 targetTypeBaseType = new BinaryType(null, lengths, null);
350 return targetTypeBaseType;
353 private TypeDefinitionBuilder findTypeDefinitionBuilder(
354 Map<String, TreeMap<Date, ModuleBuilder>> modules,
355 UnknownType unknownType, ModuleBuilder builder) {
356 Map<TypeDefinitionBuilder, TypeConstraints> result = findTypeDefinitionBuilderWithConstraints(
357 modules, unknownType, builder);
358 return result.entrySet().iterator().next().getKey();
361 private Map<TypeDefinitionBuilder, TypeConstraints> findTypeDefinitionBuilderWithConstraints(
362 Map<String, TreeMap<Date, ModuleBuilder>> modules,
363 UnknownType unknownType, ModuleBuilder builder) {
364 return findTypeDefinitionBuilderWithConstraints(new TypeConstraints(),
365 modules, unknownType, builder);
369 * Traverse through all referenced types chain until base YANG type is
373 * current type constraints
375 * all available modules
380 * @return map, where key is type referenced and value is its constraints
382 private Map<TypeDefinitionBuilder, TypeConstraints> findTypeDefinitionBuilderWithConstraints(
383 TypeConstraints constraints,
384 Map<String, TreeMap<Date, ModuleBuilder>> modules,
385 UnknownType unknownType, ModuleBuilder builder) {
386 Map<TypeDefinitionBuilder, TypeConstraints> result = new HashMap<TypeDefinitionBuilder, TypeConstraints>();
387 QName unknownTypeQName = unknownType.getQName();
388 String unknownTypeName = unknownTypeQName.getLocalName();
389 String unknownTypePrefix = unknownTypeQName.getPrefix();
391 // search for module which contains referenced typedef
392 ModuleBuilder dependentModuleBuilder;
393 if (unknownTypePrefix.equals(builder.getPrefix())) {
394 dependentModuleBuilder = builder;
396 dependentModuleBuilder = findDependentModule(modules, builder,
400 // pull all typedef statements from dependent module...
401 final Set<TypeDefinitionBuilder> typedefs = dependentModuleBuilder
402 .getModuleTypedefs();
403 // and search for referenced typedef
404 TypeDefinitionBuilder lookedUpBuilder = null;
405 for (TypeDefinitionBuilder tdb : typedefs) {
406 QName qname = tdb.getQName();
407 if (qname.getLocalName().equals(unknownTypeName)) {
408 lookedUpBuilder = tdb;
413 // if referenced type is UnknownType again, search recursively with
414 // current constraints
415 TypeDefinition<?> referencedType = lookedUpBuilder.getBaseType();
416 if (referencedType instanceof UnknownType) {
417 UnknownType unknown = (UnknownType) lookedUpBuilder.getBaseType();
419 final List<RangeConstraint> ranges = unknown.getRangeStatements();
420 constraints.addRanges(ranges);
421 final List<LengthConstraint> lengths = unknown
422 .getLengthStatements();
423 constraints.addLengths(lengths);
424 final List<PatternConstraint> patterns = unknown.getPatterns();
425 constraints.addPatterns(patterns);
426 return findTypeDefinitionBuilderWithConstraints(constraints,
427 modules, unknown, dependentModuleBuilder);
429 // pull restriction from this base type and add them to
431 if (referencedType instanceof DecimalTypeDefinition) {
432 constraints.addRanges(((DecimalTypeDefinition) referencedType)
433 .getRangeStatements());
435 .setFractionDigits(((DecimalTypeDefinition) referencedType)
436 .getFractionDigits());
437 } else if (referencedType instanceof IntegerTypeDefinition) {
438 constraints.addRanges(((IntegerTypeDefinition) referencedType)
439 .getRangeStatements());
440 } else if (referencedType instanceof StringTypeDefinition) {
441 constraints.addPatterns(((StringTypeDefinition) referencedType)
443 } else if (referencedType instanceof BinaryTypeDefinition) {
444 constraints.addLengths(((BinaryTypeDefinition) referencedType)
445 .getLengthConstraints());
447 result.put(lookedUpBuilder, constraints);
453 * Go through all augmentation definitions and resolve them. This means find
454 * referenced node and add child nodes to it.
457 * all available modules
461 private void resolveAugments(
462 Map<String, TreeMap<Date, ModuleBuilder>> modules,
463 ModuleBuilder module) {
464 Set<AugmentationSchemaBuilder> augmentBuilders = module
467 Set<AugmentationSchema> augments = new HashSet<AugmentationSchema>();
468 for (AugmentationSchemaBuilder augmentBuilder : augmentBuilders) {
469 SchemaPath augmentTargetSchemaPath = augmentBuilder.getTargetPath();
470 String prefix = null;
471 List<String> augmentTargetPath = new ArrayList<String>();
473 for (QName pathPart : augmentTargetSchemaPath.getPath()) {
474 prefix = pathPart.getPrefix();
475 augmentTargetPath.add(pathPart.getLocalName());
477 ModuleBuilder dependentModule = findDependentModule(modules,
480 augmentTargetPath.add(0, dependentModule.getName());
484 AugmentationTargetBuilder augmentTarget = (AugmentationTargetBuilder) dependentModule
485 .getNode(augmentTargetPath);
486 AugmentationSchema result = augmentBuilder.build();
487 augmentTarget.addAugmentation(result);
488 fillAugmentTarget(augmentBuilder, (ChildNodeBuilder) augmentTarget);
489 augments.add(result);
491 module.setAugmentations(augments);
495 * Add all augment's child nodes to given target.
500 private void fillAugmentTarget(AugmentationSchemaBuilder augment,
501 ChildNodeBuilder target) {
502 for (DataSchemaNodeBuilder builder : augment.getChildNodes()) {
503 builder.setAugmenting(true);
504 target.addChildNode(builder);
509 * Go through identity statements defined in current module and resolve
510 * their 'base' statement if present.
515 * module being resolved
517 private void resolveIdentities(
518 Map<String, TreeMap<Date, ModuleBuilder>> modules,
519 ModuleBuilder module) {
520 Set<IdentitySchemaNodeBuilder> identities = module.getAddedIdentities();
521 for (IdentitySchemaNodeBuilder identity : identities) {
522 String baseIdentityName = identity.getBaseIdentityName();
523 if (baseIdentityName != null) {
524 String baseIdentityPrefix = null;
525 String baseIdentityLocalName = null;
526 if (baseIdentityName.contains(":")) {
527 String[] splitted = baseIdentityName.split(":");
528 baseIdentityPrefix = splitted[0];
529 baseIdentityLocalName = splitted[1];
531 baseIdentityPrefix = module.getPrefix();
532 baseIdentityLocalName = baseIdentityName;
534 ModuleBuilder dependentModule;
535 if (baseIdentityPrefix.equals(module.getPrefix())) {
536 dependentModule = module;
538 dependentModule = findDependentModule(modules, module,
542 Set<IdentitySchemaNodeBuilder> dependentModuleIdentities = dependentModule
543 .getAddedIdentities();
544 for (IdentitySchemaNodeBuilder idBuilder : dependentModuleIdentities) {
545 if (idBuilder.getQName().getLocalName()
546 .equals(baseIdentityLocalName)) {
547 identity.setBaseIdentity(idBuilder);
555 * Find dependent module based on given prefix
558 * all available modules
562 * target module prefix
563 * @return dependent module builder
565 private ModuleBuilder findDependentModule(
566 Map<String, TreeMap<Date, ModuleBuilder>> modules,
567 ModuleBuilder module, String prefix) {
568 ModuleImport dependentModuleImport = getModuleImport(module, prefix);
569 String dependentModuleName = dependentModuleImport.getModuleName();
570 Date dependentModuleRevision = dependentModuleImport.getRevision();
572 TreeMap<Date, ModuleBuilder> moduleBuildersByRevision = modules
573 .get(dependentModuleName);
574 ModuleBuilder dependentModule;
575 if (dependentModuleRevision == null) {
576 dependentModule = moduleBuildersByRevision.lastEntry().getValue();
578 dependentModule = moduleBuildersByRevision
579 .get(dependentModuleRevision);
581 return dependentModule;
585 * Get module import referenced by given prefix.
590 * prefix associated with import
591 * @return ModuleImport based on given prefix
593 private ModuleImport getModuleImport(ModuleBuilder builder, String prefix) {
594 ModuleImport moduleImport = null;
595 for (ModuleImport mi : builder.getModuleImports()) {
596 if (mi.getPrefix().equals(prefix)) {
605 * Helper method for resolving special 'min' or 'max' values in range
613 * all available modules
617 private void resolveRanges(List<RangeConstraint> ranges,
618 TypeDefinitionBuilder targetType,
619 Map<String, TreeMap<Date, ModuleBuilder>> modules,
620 ModuleBuilder builder) {
621 if (ranges != null && ranges.size() > 0) {
622 Long min = (Long) ranges.get(0).getMin();
623 Long max = (Long) ranges.get(ranges.size() - 1).getMax();
624 // if range contains one of the special values 'min' or 'max'
625 if (min.equals(Long.MIN_VALUE) || max.equals(Long.MAX_VALUE)) {
626 Long[] values = parseRangeConstraint(targetType, modules,
628 if (min.equals(Long.MIN_VALUE)) {
630 RangeConstraint oldFirst = ranges.get(0);
631 RangeConstraint newFirst = BaseConstraints.rangeConstraint(
632 min, oldFirst.getMax(), oldFirst.getDescription(),
633 oldFirst.getReference());
634 ranges.set(0, newFirst);
636 if (max.equals(Long.MAX_VALUE)) {
638 RangeConstraint oldLast = ranges.get(ranges.size() - 1);
639 RangeConstraint newLast = BaseConstraints.rangeConstraint(
640 oldLast.getMin(), max, oldLast.getDescription(),
641 oldLast.getReference());
642 ranges.set(ranges.size() - 1, newLast);
649 * Helper method for resolving special 'min' or 'max' values in length
657 * all available modules
661 private void resolveLengths(List<LengthConstraint> lengths,
662 TypeDefinitionBuilder targetType,
663 Map<String, TreeMap<Date, ModuleBuilder>> modules,
664 ModuleBuilder builder) {
665 if (lengths != null && lengths.size() > 0) {
666 Long min = lengths.get(0).getMin();
667 Long max = lengths.get(lengths.size() - 1).getMax();
668 // if length contains one of the special values 'min' or 'max'
669 if (min.equals(Long.MIN_VALUE) || max.equals(Long.MAX_VALUE)) {
670 Long[] values = parseRangeConstraint(targetType, modules,
672 if (min.equals(Long.MIN_VALUE)) {
674 LengthConstraint oldFirst = lengths.get(0);
675 LengthConstraint newFirst = BaseConstraints
676 .lengthConstraint(min, oldFirst.getMax(),
677 oldFirst.getDescription(),
678 oldFirst.getReference());
679 lengths.set(0, newFirst);
681 if (max.equals(Long.MAX_VALUE)) {
683 LengthConstraint oldLast = lengths.get(lengths.size() - 1);
684 LengthConstraint newLast = BaseConstraints
685 .lengthConstraint(oldLast.getMin(), max,
686 oldLast.getDescription(),
687 oldLast.getReference());
688 lengths.set(lengths.size() - 1, newLast);
694 private Long[] parseRangeConstraint(TypeDefinitionBuilder targetType,
695 Map<String, TreeMap<Date, ModuleBuilder>> modules,
696 ModuleBuilder builder) {
697 TypeDefinition<?> targetBaseType = targetType.getBaseType();
699 if (targetBaseType instanceof IntegerTypeDefinition) {
700 IntegerTypeDefinition itd = (IntegerTypeDefinition) targetBaseType;
701 List<RangeConstraint> ranges = itd.getRangeStatements();
702 Long min = (Long) ranges.get(0).getMin();
703 Long max = (Long) ranges.get(ranges.size() - 1).getMax();
704 return new Long[] { min, max };
705 } else if (targetBaseType instanceof DecimalTypeDefinition) {
706 DecimalTypeDefinition dtd = (DecimalTypeDefinition) targetBaseType;
707 List<RangeConstraint> ranges = dtd.getRangeStatements();
708 Long min = (Long) ranges.get(0).getMin();
709 Long max = (Long) ranges.get(ranges.size() - 1).getMax();
710 return new Long[] { min, max };
712 return parseRangeConstraint(
713 findTypeDefinitionBuilder(modules,
714 (UnknownType) targetBaseType, builder), modules,
719 private Date createEpochTime() {
720 Calendar c = Calendar.getInstance();
721 c.setTimeInMillis(0);
725 private static class SchemaContextImpl implements SchemaContext {
726 private final Set<Module> modules;
728 private SchemaContextImpl(Set<Module> modules) {
729 this.modules = modules;
733 public Set<DataSchemaNode> getDataDefinitions() {
734 final Set<DataSchemaNode> dataDefs = new HashSet<DataSchemaNode>();
735 for (Module m : modules) {
736 dataDefs.addAll(m.getChildNodes());
742 public Set<Module> getModules() {
747 public Set<NotificationDefinition> getNotifications() {
748 final Set<NotificationDefinition> notifications = new HashSet<NotificationDefinition>();
749 for (Module m : modules) {
750 notifications.addAll(m.getNotifications());
752 return notifications;
756 public Set<RpcDefinition> getOperations() {
757 final Set<RpcDefinition> rpcs = new HashSet<RpcDefinition>();
758 for (Module m : modules) {
759 rpcs.addAll(m.getRpcs());
765 public Set<ExtensionDefinition> getExtensions() {
766 final Set<ExtensionDefinition> extensions = new HashSet<ExtensionDefinition>();
767 for (Module m : modules) {
768 extensions.addAll(m.getExtensionSchemaNodes());
774 private static class TypeConstraints {
775 private final List<RangeConstraint> ranges = new ArrayList<RangeConstraint>();
776 private final List<LengthConstraint> lengths = new ArrayList<LengthConstraint>();
777 private final List<PatternConstraint> patterns = new ArrayList<PatternConstraint>();
778 private Integer fractionDigits;
780 public List<RangeConstraint> getRanges() {
784 public void addRanges(List<RangeConstraint> ranges) {
785 this.ranges.addAll(0, ranges);
788 public List<LengthConstraint> getLengths() {
792 public void addLengths(List<LengthConstraint> lengths) {
793 this.lengths.addAll(0, lengths);
796 public List<PatternConstraint> getPatterns() {
800 public void addPatterns(List<PatternConstraint> patterns) {
801 this.patterns.addAll(0, patterns);
804 public Integer getFractionDigits() {
805 return fractionDigits;
808 public void setFractionDigits(Integer fractionDigits) {
809 if (fractionDigits != null) {
810 this.fractionDigits = fractionDigits;