Refactor ExplicitStatement
[yangtools.git] / model / yang-model-spi / src / main / java / org / opendaylight / yangtools / yang / model / spi / meta / StatementDeclarations.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.model.spi.meta;
10
11 import static com.google.common.base.Preconditions.checkArgument;
12 import static java.util.Objects.requireNonNull;
13
14 import org.eclipse.jdt.annotation.NonNull;
15 import org.eclipse.jdt.annotation.Nullable;
16 import org.opendaylight.yangtools.yang.model.api.meta.StatementDeclaration;
17 import org.opendaylight.yangtools.yang.model.api.meta.StatementSourceReference;
18
19 /**
20  * Factory for creating default {@link StatementDeclaration} implementations. This is preferred source of
21  * {@link StatementSourceReference} for implementations of YANG / YIN statement stream sources.
22  *
23  * <p>
24  * To create source reference use one of this static factories:
25  * <ul>
26  *   <li>{@link #inText(String, int, int)} - provides most specific reference of statement location, this is most
27  *       preferred since it provides most context to debug YANG model</li>
28  *   <li>{@link #inText(int, int)}- provides location in text without knowing the name of the text file</li>
29  * </ul>
30  */
31 public final class StatementDeclarations {
32     private static class InTextInt extends StatementDeclaration.InText {
33         private final int startLine;
34         private final int startColumn;
35
36         InTextInt(final int startLine, final int startColumn) {
37             this.startLine = startLine;
38             this.startColumn = startColumn;
39         }
40
41         @Override
42         public int startLine() {
43             return startLine;
44         }
45
46         @Override
47         public int startColumn() {
48             return startColumn;
49         }
50     }
51
52     private static class InTextShort extends StatementDeclaration.InText {
53         private final short startLine;
54         private final short startColumn;
55
56         InTextShort(final short startLine, final short startColumn) {
57             this.startLine = startLine;
58             this.startColumn = startColumn;
59         }
60
61         @Override
62         public int startLine() {
63             return Short.toUnsignedInt(startLine);
64         }
65
66         @Override
67         public int startColumn() {
68             return Short.toUnsignedInt(startColumn);
69         }
70     }
71
72     private static final class InTextFileInt extends StatementDeclaration.InTextFile {
73         private final @NonNull String fileName;
74         private final int startLine;
75         private final int startColumn;
76
77         InTextFileInt(final String fileName, final int startLine, final int startColumn) {
78             this.fileName = requireNonNull(fileName);
79             this.startLine = startLine;
80             this.startColumn = startColumn;
81         }
82
83         @Override
84         public int startLine() {
85             return startLine;
86         }
87
88         @Override
89         public int startColumn() {
90             return startColumn;
91         }
92
93         @Override
94         public String fileName() {
95             return fileName;
96         }
97     }
98
99     private static final class InTextFileShort extends StatementDeclaration.InTextFile {
100         private final @NonNull String fileName;
101         private final short startLine;
102         private final short startColumn;
103
104         InTextFileShort(final String fileName, final short startLine, final short startColumn) {
105             this.fileName = requireNonNull(fileName);
106             this.startLine = startLine;
107             this.startColumn = startColumn;
108         }
109
110         @Override
111         public int startLine() {
112             return Short.toUnsignedInt(startLine);
113         }
114
115         @Override
116         public int startColumn() {
117             return Short.toUnsignedInt(startColumn);
118         }
119
120         @Override
121         public String fileName() {
122             return fileName;
123         }
124     }
125
126     private StatementDeclarations() {
127         // Hidden on purpose
128     }
129
130     public static StatementDeclaration.@NonNull InText inText(final int startLine, final int startColumn) {
131         return canUseShort(startLine, startColumn) ? new InTextShort((short) startLine, (short) startColumn)
132             : new InTextInt(startLine, startColumn);
133     }
134
135     public static StatementDeclaration.@NonNull InText inText(final @Nullable String fileName, final int startLine,
136             final int startColumn) {
137         if (fileName == null) {
138             return inText(startLine, startColumn);
139         }
140         checkArgument(!fileName.isEmpty(), "Invalid empty file name");
141         return canUseShort(startLine, startColumn)
142             ? new InTextFileShort(fileName, (short) startLine, (short) startColumn)
143                 : new InTextFileInt(fileName, startLine, startColumn);
144     }
145
146     private static boolean canUseShort(final int startLine, final int startColumn) {
147         checkArgument(startLine > 0, "Invalid start line %s", startLine);
148         checkArgument(startColumn > 0, "Invalid start column %s", startColumn);
149         return startLine <= 65535 && startColumn <= 65535;
150     }
151 }