Remove hashCode()/equals() from SchemaNode implementations
[yangtools.git] / yang / yang-parser-rfc7950 / src / main / java / org / opendaylight / yangtools / yang / parser / rfc7950 / stmt / submodule / SubmoduleEffectiveStatementImpl.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.rfc7950.stmt.submodule;
9
10 import static com.google.common.base.Preconditions.checkState;
11 import static org.opendaylight.yangtools.yang.parser.spi.meta.StmtContextUtils.firstAttributeOf;
12
13 import com.google.common.collect.ImmutableSet;
14 import com.google.common.collect.Iterables;
15 import java.util.HashSet;
16 import java.util.Map;
17 import java.util.Optional;
18 import java.util.Set;
19 import org.eclipse.jdt.annotation.NonNull;
20 import org.opendaylight.yangtools.yang.common.QNameModule;
21 import org.opendaylight.yangtools.yang.common.Revision;
22 import org.opendaylight.yangtools.yang.model.api.Module;
23 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
24 import org.opendaylight.yangtools.yang.model.api.stmt.BelongsToStatement;
25 import org.opendaylight.yangtools.yang.model.api.stmt.RevisionEffectiveStatement;
26 import org.opendaylight.yangtools.yang.model.api.stmt.SubmoduleEffectiveStatement;
27 import org.opendaylight.yangtools.yang.model.api.stmt.SubmoduleStatement;
28 import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.AbstractEffectiveModule;
29 import org.opendaylight.yangtools.yang.parser.spi.meta.MutableStatement;
30 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
31 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext.Mutable;
32 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContextUtils;
33 import org.opendaylight.yangtools.yang.parser.spi.source.IncludedSubmoduleNameToModuleCtx;
34 import org.opendaylight.yangtools.yang.parser.spi.source.ModuleNameToModuleQName;
35 import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
36
37 final class SubmoduleEffectiveStatementImpl extends AbstractEffectiveModule<SubmoduleStatement>
38         implements SubmoduleEffectiveStatement, MutableStatement {
39
40     private final QNameModule qnameModule;
41
42     private Set<StmtContext<?, SubmoduleStatement, EffectiveStatement<String, SubmoduleStatement>>> submoduleContexts;
43     private ImmutableSet<Module> submodules;
44     private boolean sealed;
45
46     SubmoduleEffectiveStatementImpl(final StmtContext<String, SubmoduleStatement, SubmoduleEffectiveStatement> ctx) {
47         super(ctx, findSubmodulePrefix(ctx));
48
49         final String belongsToModuleName = firstAttributeOf(ctx.declaredSubstatements(), BelongsToStatement.class);
50         final QNameModule belongsToModuleQName = ctx.getFromNamespace(ModuleNameToModuleQName.class,
51                 belongsToModuleName);
52
53         final Optional<Revision> submoduleRevision = findFirstEffectiveSubstatementArgument(
54             RevisionEffectiveStatement.class);
55         this.qnameModule = QNameModule.create(belongsToModuleQName.getNamespace(), submoduleRevision).intern();
56
57         /*
58          * Because of possible circular chains of includes between submodules we can
59          * collect only submodule contexts here and then build them during
60          * sealing of this statement.
61          */
62         final Map<String, StmtContext<?, ?, ?>> includedSubmodulesMap = ctx.getAllFromCurrentStmtCtxNamespace(
63             IncludedSubmoduleNameToModuleCtx.class);
64         if (includedSubmodulesMap != null) {
65             final Set<StmtContext<?, SubmoduleStatement, EffectiveStatement<String, SubmoduleStatement>>>
66                 submoduleContextsInit = new HashSet<>();
67             for (final StmtContext<?, ?, ?> submoduleCtx : includedSubmodulesMap.values()) {
68                 submoduleContextsInit.add(
69                     (StmtContext<?, SubmoduleStatement, EffectiveStatement<String, SubmoduleStatement>>)submoduleCtx);
70             }
71             submoduleContexts = ImmutableSet.copyOf(submoduleContextsInit);
72         } else {
73             submoduleContexts = ImmutableSet.of();
74         }
75
76         if (!submoduleContexts.isEmpty()) {
77             ((Mutable<?, ?, ?>) ctx).addMutableStmtToSeal(this);
78             sealed = false;
79         } else {
80             submodules = ImmutableSet.of();
81             sealed = true;
82         }
83     }
84
85     @Override
86     public QNameModule getQNameModule() {
87         return qnameModule;
88     }
89
90     @Override
91     public Set<Module> getSubmodules() {
92         checkState(sealed, "Attempt to get base submodules from unsealed submodule effective statement %s",
93             qnameModule);
94         return submodules;
95     }
96
97     @Override
98     public void seal() {
99         if (!sealed) {
100             submodules = ImmutableSet.copyOf(Iterables.transform(submoduleContexts,
101                 ctx -> (Module) ctx.buildEffective()));
102             submoduleContexts = ImmutableSet.of();
103             sealed = true;
104         }
105     }
106
107     private static @NonNull String findSubmodulePrefix(final StmtContext<String, ?, ?> ctx) {
108         final String name = ctx.getStatementArgument();
109         final StmtContext<?, ?, ?> belongsTo = SourceException.throwIfNull(
110                 StmtContextUtils.findFirstDeclaredSubstatement(ctx, BelongsToStatement.class),
111                 ctx.getStatementSourceReference(), "Unable to find belongs-to statement in submodule %s.", name);
112         return findPrefix(belongsTo, "submodule", name);
113     }
114 }