cea919e7e02dc303ef94b187e3a0af95831609b9
[yangtools.git] / yang / yang-parser-impl / src / main / java / org / opendaylight / yangtools / yang / parser / stmt / rfc6020 / effective / ChoiceEffectiveStatementImpl.java
1 /*
2  * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.yangtools.yang.parser.stmt.rfc6020.effective;
9
10 import com.google.common.collect.ImmutableSet;
11 import com.google.common.collect.ImmutableSortedMap;
12 import java.util.LinkedHashSet;
13 import java.util.Objects;
14 import java.util.Optional;
15 import java.util.Set;
16 import java.util.SortedMap;
17 import java.util.TreeMap;
18 import org.opendaylight.yangtools.yang.common.QName;
19 import org.opendaylight.yangtools.yang.model.api.AugmentationSchemaNode;
20 import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
21 import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
22 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
23 import org.opendaylight.yangtools.yang.model.api.DerivableSchemaNode;
24 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
25 import org.opendaylight.yangtools.yang.model.api.stmt.ChoiceStatement;
26 import org.opendaylight.yangtools.yang.model.api.stmt.MandatoryEffectiveStatement;
27 import org.opendaylight.yangtools.yang.parser.spi.meta.InferenceException;
28 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
29 import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
30 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.YangValidationBundles;
31
32 public final class ChoiceEffectiveStatementImpl extends AbstractEffectiveDataSchemaNode<ChoiceStatement> implements
33         ChoiceSchemaNode, DerivableSchemaNode {
34
35     private final Set<AugmentationSchemaNode> augmentations;
36     private final SortedMap<QName, ChoiceCaseNode> cases;
37     private final ChoiceCaseNode defaultCase;
38     private final ChoiceSchemaNode original;
39     private final boolean mandatory;
40
41     public ChoiceEffectiveStatementImpl(
42             final StmtContext<QName, ChoiceStatement, EffectiveStatement<QName, ChoiceStatement>> ctx) {
43         super(ctx);
44         this.original = (ChoiceSchemaNode) ctx.getOriginalCtx().map(StmtContext::buildEffective).orElse(null);
45
46         // initSubstatementCollectionsAndFields
47         final Set<AugmentationSchemaNode> augmentationsInit = new LinkedHashSet<>();
48         final SortedMap<QName, ChoiceCaseNode> casesInit = new TreeMap<>();
49
50         for (final EffectiveStatement<?, ?> effectiveStatement : effectiveSubstatements()) {
51             if (effectiveStatement instanceof AugmentationSchemaNode) {
52                 final AugmentationSchemaNode augmentationSchema = (AugmentationSchemaNode) effectiveStatement;
53                 augmentationsInit.add(augmentationSchema);
54             }
55             if (effectiveStatement instanceof ChoiceCaseNode) {
56                 final ChoiceCaseNode choiceCaseNode = (ChoiceCaseNode) effectiveStatement;
57                 // FIXME: we may be overwriting a previous entry, is that really okay?
58                 casesInit.put(choiceCaseNode.getQName(), choiceCaseNode);
59             }
60             if (YangValidationBundles.SUPPORTED_CASE_SHORTHANDS.contains(effectiveStatement.statementDefinition())) {
61                 final DataSchemaNode dataSchemaNode = (DataSchemaNode) effectiveStatement;
62                 final ChoiceCaseNode shorthandCase = new CaseShorthandImpl(dataSchemaNode);
63                 // FIXME: we may be overwriting a previous entry, is that really okay?
64                 casesInit.put(shorthandCase.getQName(), shorthandCase);
65                 if (dataSchemaNode.isAugmenting() && !this.augmenting) {
66                     resetAugmenting(dataSchemaNode);
67                 }
68             }
69         }
70
71         this.augmentations = ImmutableSet.copyOf(augmentationsInit);
72         this.cases = ImmutableSortedMap.copyOfSorted(casesInit);
73
74         final DefaultEffectiveStatementImpl defaultStmt = firstEffective(DefaultEffectiveStatementImpl.class);
75         if (defaultStmt != null) {
76             final QName qname;
77             try {
78                 qname = QName.create(getQName(), defaultStmt.argument());
79             } catch (IllegalArgumentException e) {
80                 throw new SourceException(ctx.getStatementSourceReference(), "Default statement has invalid name '%s'",
81                     defaultStmt.argument(), e);
82             }
83
84             // FIXME: this does not work with submodules, as they are
85             defaultCase = InferenceException.throwIfNull(cases.get(qname), ctx.getStatementSourceReference(),
86                 "Default statement refers to missing case %s", qname);
87         } else {
88             defaultCase = null;
89         }
90
91         final MandatoryEffectiveStatement mandatoryStmt = firstEffective(MandatoryEffectiveStatement.class);
92         mandatory = mandatoryStmt == null ? false : mandatoryStmt.argument().booleanValue();
93     }
94
95     private static void resetAugmenting(final DataSchemaNode dataSchemaNode) {
96         if (dataSchemaNode instanceof LeafEffectiveStatementImpl) {
97             final LeafEffectiveStatementImpl leaf = (LeafEffectiveStatementImpl) dataSchemaNode;
98             leaf.augmenting = false;
99         } else if (dataSchemaNode instanceof ContainerEffectiveStatementImpl) {
100             final ContainerEffectiveStatementImpl container = (ContainerEffectiveStatementImpl) dataSchemaNode;
101             container.augmenting = false;
102         } else if (dataSchemaNode instanceof LeafListEffectiveStatementImpl) {
103             final LeafListEffectiveStatementImpl leafList = (LeafListEffectiveStatementImpl) dataSchemaNode;
104             leafList.augmenting = false;
105         } else if (dataSchemaNode instanceof ListEffectiveStatementImpl) {
106             final ListEffectiveStatementImpl list = (ListEffectiveStatementImpl) dataSchemaNode;
107             list.augmenting = false;
108         } else if (dataSchemaNode instanceof AnyXmlEffectiveStatementImpl) {
109             final AnyXmlEffectiveStatementImpl anyXml = (AnyXmlEffectiveStatementImpl) dataSchemaNode;
110             anyXml.augmenting = false;
111         }
112     }
113
114     @Override
115     public Optional<ChoiceSchemaNode> getOriginal() {
116         return Optional.ofNullable(original);
117     }
118
119     @Override
120     public Set<AugmentationSchemaNode> getAvailableAugmentations() {
121         return augmentations;
122     }
123
124     @Override
125     public SortedMap<QName, ChoiceCaseNode> getCases() {
126         return cases;
127     }
128
129     @Override
130     public Optional<ChoiceCaseNode> getDefaultCase() {
131         return Optional.ofNullable(defaultCase);
132     }
133
134     @Override
135     public boolean isMandatory() {
136         return mandatory;
137     }
138
139     @Override
140     public int hashCode() {
141         final int prime = 31;
142         int result = 1;
143         result = prime * result + Objects.hashCode(getQName());
144         result = prime * result + Objects.hashCode(getPath());
145         return result;
146     }
147
148     @Override
149     public boolean equals(final Object obj) {
150         if (this == obj) {
151             return true;
152         }
153         if (obj == null) {
154             return false;
155         }
156         if (getClass() != obj.getClass()) {
157             return false;
158         }
159         final ChoiceEffectiveStatementImpl other = (ChoiceEffectiveStatementImpl) obj;
160         return Objects.equals(getQName(), other.getQName()) && Objects.equals(getPath(), other.getPath());
161     }
162
163     @Override
164     public String toString() {
165         return ChoiceEffectiveStatementImpl.class.getSimpleName() + "["
166                 + "qname=" + getQName()
167                 + "]";
168     }
169 }