1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.maven.api.model;
20
21 import java.io.Serializable;
22 import java.util.Collection;
23 import java.util.Collections;
24 import java.util.LinkedHashMap;
25 import java.util.Map;
26 import java.util.Objects;
27
28
29
30
31
32
33
34
35
36
37 public class InputLocation implements Serializable, InputLocationTracker {
38 private final int lineNumber;
39 private final int columnNumber;
40 private final InputSource source;
41 private final Map<Object, InputLocation> locations;
42 private final InputLocation importedFrom;
43
44 public InputLocation(InputSource source) {
45 this.lineNumber = -1;
46 this.columnNumber = -1;
47 this.source = source;
48 this.locations = Collections.singletonMap(0, this);
49 this.importedFrom = null;
50 }
51
52 public InputLocation(int lineNumber, int columnNumber) {
53 this(lineNumber, columnNumber, null, null);
54 }
55
56 public InputLocation(int lineNumber, int columnNumber, InputSource source) {
57 this(lineNumber, columnNumber, source, null);
58 }
59
60 public InputLocation(int lineNumber, int columnNumber, InputSource source, Object selfLocationKey) {
61 this.lineNumber = lineNumber;
62 this.columnNumber = columnNumber;
63 this.source = source;
64 this.locations =
65 selfLocationKey != null ? Collections.singletonMap(selfLocationKey, this) : Collections.emptyMap();
66 this.importedFrom = null;
67 }
68
69 public InputLocation(int lineNumber, int columnNumber, InputSource source, Map<Object, InputLocation> locations) {
70 this.lineNumber = lineNumber;
71 this.columnNumber = columnNumber;
72 this.source = source;
73 this.locations = ImmutableCollections.copy(locations);
74 this.importedFrom = null;
75 }
76
77 public InputLocation(InputLocation original) {
78 this.lineNumber = original.lineNumber;
79 this.columnNumber = original.columnNumber;
80 this.source = original.source;
81 this.locations = original.locations;
82 this.importedFrom = original.importedFrom;
83 }
84
85 public int getLineNumber() {
86 return lineNumber;
87 }
88
89 public int getColumnNumber() {
90 return columnNumber;
91 }
92
93 public InputSource getSource() {
94 return source;
95 }
96
97 @Override
98 public InputLocation getLocation(Object key) {
99 Objects.requireNonNull(key, "key");
100 return locations != null ? locations.get(key) : null;
101 }
102
103 public Map<Object, InputLocation> getLocations() {
104 return locations;
105 }
106
107
108
109
110
111
112
113
114 @Override
115 public InputLocation getImportedFrom() {
116 return importedFrom;
117 }
118
119
120
121
122
123
124
125
126
127 public static InputLocation merge(InputLocation target, InputLocation source, boolean sourceDominant) {
128 if (source == null) {
129 return target;
130 } else if (target == null) {
131 return source;
132 }
133
134 Map<Object, InputLocation> locations;
135 Map<Object, InputLocation> sourceLocations = source.locations;
136 Map<Object, InputLocation> targetLocations = target.locations;
137 if (sourceLocations == null) {
138 locations = targetLocations;
139 } else if (targetLocations == null) {
140 locations = sourceLocations;
141 } else {
142 locations = new LinkedHashMap<>();
143 locations.putAll(sourceDominant ? targetLocations : sourceLocations);
144 locations.putAll(sourceDominant ? sourceLocations : targetLocations);
145 }
146
147 return new InputLocation(-1, -1, InputSource.merge(source.getSource(), target.getSource()), locations);
148 }
149
150
151
152
153
154
155
156
157
158
159 public static InputLocation merge(InputLocation target, InputLocation source, Collection<Integer> indices) {
160 if (source == null) {
161 return target;
162 } else if (target == null) {
163 return source;
164 }
165
166 Map<Object, InputLocation> locations;
167 Map<Object, InputLocation> sourceLocations = source.locations;
168 Map<Object, InputLocation> targetLocations = target.locations;
169 if (sourceLocations == null) {
170 locations = targetLocations;
171 } else if (targetLocations == null) {
172 locations = sourceLocations;
173 } else {
174 locations = new LinkedHashMap<>();
175 for (int index : indices) {
176 InputLocation location;
177 if (index < 0) {
178 location = sourceLocations.get(~index);
179 } else {
180 location = targetLocations.get(index);
181 }
182 locations.put(locations.size(), location);
183 }
184 }
185
186 return new InputLocation(-1, -1, InputSource.merge(source.getSource(), target.getSource()), locations);
187 }
188
189
190
191
192
193
194 public interface StringFormatter {
195
196
197
198
199
200
201
202
203 String toString(InputLocation location);
204 }
205
206 @Override
207 public String toString() {
208 return String.format("%s @ %d:%d", source != null ? source.getLocation() : "n/a", lineNumber, columnNumber);
209 }
210 }