Promote StatementSourceReference to model.api.meta
[yangtools.git] / parser / yang-parser-spi / src / main / java / org / opendaylight / yangtools / yang / parser / spi / source / ExplicitStatement.java
1 /*
2  * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
3  * Copyright (c) 2021 PANTHEON.tech, s.r.o.
4  *
5  * This program and the accompanying materials are made available under the
6  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
7  * and is available at http://www.eclipse.org/legal/epl-v10.html
8  */
9 package org.opendaylight.yangtools.yang.parser.spi.source;
10
11 import static com.google.common.base.Preconditions.checkArgument;
12 import static com.google.common.base.Verify.verifyNotNull;
13
14 import com.google.common.annotations.Beta;
15 import java.util.Objects;
16 import org.eclipse.jdt.annotation.NonNull;
17 import org.eclipse.jdt.annotation.Nullable;
18 import org.opendaylight.yangtools.yang.model.api.meta.DeclarationInFile;
19 import org.opendaylight.yangtools.yang.model.api.meta.DeclarationInText;
20 import org.opendaylight.yangtools.yang.model.api.meta.DeclarationReference;
21 import org.opendaylight.yangtools.yang.model.api.meta.StatementOrigin;
22 import org.opendaylight.yangtools.yang.model.api.meta.StatementSourceReference;
23
24 /**
25  * Reference of statement source present in textual source format. Utility implementation
26  * of {@link StatementSourceReference} for textual sources, this is preferred {@link StatementSourceReference}
27  * for implementations of YANG / YIN statement stream sources.
28  *
29  * <p>
30  * To create source reference use one of this static factories:
31  * <ul>
32  *   <li>{@link #atPosition(String, int, int)} - provides most specific reference of statement location, this is most
33  *       preferred since it provides most context to debug YANG model.</li>
34  *   <li>{@link #atPosition(int, int)}- provides location in text without knowing the name of the text file.</li>
35  *   <li>{@link #inFile(String)}- provides a source name.</li>
36  * </ul>
37  */
38 @Beta
39 public abstract class ExplicitStatement extends StatementSourceReference implements DeclarationReference {
40     private static final class InFile extends ExplicitStatement implements DeclarationInFile {
41         InFile(final String fileName) {
42             super(fileName, -1, -1);
43             checkArgument(!fileName.isEmpty(), "Invalid empty file name");
44         }
45
46         @Override
47         public String fileName() {
48             return verifyNotNull(file());
49         }
50     }
51
52     private static class InText extends ExplicitStatement implements DeclarationInText {
53         InText(final String file, final int line, final int column) {
54             super(file, line, column);
55             checkArgument(line > 0, "Invalid start line %s", line);
56             checkArgument(column > 0, "Invalid start column %s", column);
57         }
58
59         @Override
60         public int startLine() {
61             return line();
62         }
63
64         @Override
65         public int startColumn() {
66             return column();
67         }
68     }
69
70     private static final class InTextFile extends InText implements DeclarationInFile {
71         InTextFile(final String fileName, final int line, final int column) {
72             super(fileName, line, column);
73             checkArgument(!fileName.isEmpty(), "Invalid empty file name");
74         }
75
76         @Override
77         public String fileName() {
78             return verifyNotNull(file());
79         }
80     }
81
82     private final String file;
83     private final int line;
84     private final int column;
85
86     ExplicitStatement(final String file, final int line, final int column) {
87         this.file = file;
88         this.line = line;
89         this.column = column;
90     }
91
92     public static @NonNull ExplicitStatement atPosition(final int line, final int column) {
93         return new InText(null, line, column);
94     }
95
96     public static @NonNull ExplicitStatement atPosition(final @Nullable String fileName, final int line,
97             final int column) {
98         return fileName == null ? atPosition(line, column) : new InTextFile(fileName, line, column);
99     }
100
101     public static @NonNull ExplicitStatement inFile(final @NonNull String fileName) {
102         return new InFile(fileName);
103     }
104
105     @Override
106     public final StatementOrigin statementOrigin() {
107         return StatementOrigin.DECLARATION;
108     }
109
110     @Override
111     public final DeclarationReference declarationReference() {
112         return this;
113     }
114
115     @Override
116     public final String toHumanReadable() {
117         final StringBuilder sb = new StringBuilder();
118         sb.append(file != null ? file : "<UNKNOWN>");
119         if (line > 0) {
120             sb.append(':').append(line);
121         }
122         if (column > 0) {
123             sb.append(':').append(column);
124         }
125         return sb.toString();
126     }
127
128     @Override
129     public final int hashCode() {
130         return Objects.hash(file(), line(), column());
131     }
132
133     @Override
134     public final boolean equals(final Object obj) {
135         if (this == obj) {
136             return true;
137         }
138         if (obj == null || !getClass().equals(obj.getClass())) {
139             return false;
140         }
141         final ExplicitStatement other = (ExplicitStatement) obj;
142         return line == other.line && column == other.column && Objects.equals(file, other.file);
143     }
144
145     @Override
146     public final String toString() {
147         return toHumanReadable();
148     }
149
150     final String file() {
151         return file;
152     }
153
154     final int line() {
155         return line;
156     }
157
158     final int column() {
159         return column;
160     }
161 }