YANGTOOLS-706: Retrofit EffectiveStatement interfaces into parser
[yangtools.git] / yang / yang-parser-impl / src / main / java / org / opendaylight / yangtools / yang / parser / stmt / rfc6020 / effective / ImportEffectiveStatementImpl.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.base.MoreObjects;
11 import java.util.Objects;
12 import java.util.Optional;
13 import org.opendaylight.yangtools.concepts.SemVer;
14 import org.opendaylight.yangtools.yang.common.QNameModule;
15 import org.opendaylight.yangtools.yang.common.Revision;
16 import org.opendaylight.yangtools.yang.model.api.ModuleImport;
17 import org.opendaylight.yangtools.yang.model.api.stmt.ImportEffectiveStatement;
18 import org.opendaylight.yangtools.yang.model.api.stmt.ImportStatement;
19 import org.opendaylight.yangtools.yang.model.repo.api.SemVerSourceIdentifier;
20 import org.opendaylight.yangtools.yang.parser.spi.meta.MissingSubstatementException;
21 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
22 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContextUtils;
23 import org.opendaylight.yangtools.yang.parser.spi.source.ImportPrefixToSemVerSourceIdentifier;
24 import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
25
26 public class ImportEffectiveStatementImpl extends DeclaredEffectiveStatementBase<String, ImportStatement>
27         implements ImportEffectiveStatement, ModuleImport {
28
29     private final String moduleName;
30     private final Revision revision;
31     private final SemVer semVer;
32     private final String prefix;
33     private final String description;
34     private final String reference;
35
36     public ImportEffectiveStatementImpl(final StmtContext<String, ImportStatement, ?> ctx) {
37         super(ctx);
38
39         moduleName = ctx.getStatementArgument();
40         final PrefixEffectiveStatementImpl prefixStmt = firstEffective(PrefixEffectiveStatementImpl.class);
41         if (prefixStmt != null) {
42             this.prefix = prefixStmt.argument();
43         } else {
44             throw new MissingSubstatementException("Prefix is mandatory substatement of import statement",
45                     ctx.getStatementSourceReference());
46         }
47
48         if (!ctx.isEnabledSemanticVersioning()) {
49             final RevisionDateEffectiveStatementImpl revisionDateStmt = firstEffective(
50                 RevisionDateEffectiveStatementImpl.class);
51             this.revision = revisionDateStmt == null ? getImportedRevision(ctx) : revisionDateStmt.argument();
52             this.semVer = null;
53         } else {
54             final SemVerSourceIdentifier importedModuleIdentifier = ctx.getFromNamespace(
55                 ImportPrefixToSemVerSourceIdentifier.class, prefix);
56             revision = importedModuleIdentifier.getRevision().orElse(null);
57             semVer = importedModuleIdentifier.getSemanticVersion().orElse(null);
58         }
59
60         final DescriptionEffectiveStatementImpl descriptionStmt = firstEffective(
61             DescriptionEffectiveStatementImpl.class);
62         this.description = descriptionStmt != null ? descriptionStmt.argument() : null;
63
64         final ReferenceEffectiveStatementImpl referenceStmt = firstEffective(ReferenceEffectiveStatementImpl.class);
65         this.reference = referenceStmt != null ? referenceStmt.argument() : null;
66     }
67
68     private Revision getImportedRevision(final StmtContext<String, ImportStatement, ?> ctx) {
69         /*
70          * When 'revision-date' of an import is not specified in yang source, we
71          * need to find revision of imported module.
72          */
73         final QNameModule importedModule = StmtContextUtils.getModuleQNameByPrefix(ctx, this.prefix);
74         SourceException.throwIfNull(importedModule, ctx.getStatementSourceReference(),
75                 "Unable to find import of module %s with prefix %s.", this.moduleName, this.prefix);
76         return importedModule.getRevision().orElse(null);
77     }
78
79     @Override
80     public String getModuleName() {
81         return moduleName;
82     }
83
84     @Override
85     public Optional<Revision> getRevision() {
86         return Optional.ofNullable(revision);
87     }
88
89     @Override
90     public Optional<SemVer> getSemanticVersion() {
91         return Optional.ofNullable(semVer);
92     }
93
94     @Override
95     public String getPrefix() {
96         return prefix;
97     }
98
99     @Override
100     public Optional<String> getDescription() {
101         return Optional.ofNullable(description);
102     }
103
104     @Override
105     public Optional<String> getReference() {
106         return Optional.ofNullable(reference);
107     }
108
109     @Override
110     public int hashCode() {
111         return Objects.hash(moduleName, revision, prefix, semVer, description, reference);
112     }
113
114     @Override
115     public boolean equals(final Object obj) {
116         if (this == obj) {
117             return true;
118         }
119         if (obj == null) {
120             return false;
121         }
122         if (getClass() != obj.getClass()) {
123             return false;
124         }
125         final ImportEffectiveStatementImpl other = (ImportEffectiveStatementImpl) obj;
126         return Objects.equals(moduleName, other.moduleName) && Objects.equals(revision, other.revision)
127                 && Objects.equals(semVer, other.semVer) && Objects.equals(prefix, other.prefix)
128                 && Objects.equals(description, other.description) && Objects.equals(reference, other.reference);
129     }
130
131     @Override
132     public String toString() {
133         return MoreObjects.toStringHelper(this).omitNullValues().add("moduleName", getModuleName())
134                 .add("revision", revision).add("version", semVer).add("prefix", getPrefix())
135                 .add("description", description).add("reference", reference).toString();
136     }
137 }