View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.model;
20  
21  import java.util.stream.Collectors;
22  
23  /**
24   * Class InputLocation.
25   *
26   * @version $Revision$ $Date$
27   */
28  @SuppressWarnings("all")
29  public final class InputLocation implements java.io.Serializable, Cloneable, InputLocationTracker {
30  
31      // --------------------------/
32      // - Class/Member Variables -/
33      // --------------------------/
34  
35      /**
36       * The one-based line number. The value will be non-positive if
37       * unknown.
38       */
39      private int lineNumber = -1;
40  
41      /**
42       * The one-based column number. The value will be non-positive
43       * if unknown.
44       */
45      private int columnNumber = -1;
46  
47      /**
48       * Field source.
49       */
50      private InputSource source;
51  
52      /**
53       * Field locations.
54       */
55      private java.util.Map<Object, InputLocation> locations;
56  
57      /**
58       * Field location.
59       */
60      private InputLocation location;
61  
62      /**
63       * Field importedFrom.
64       */
65      private InputLocation importedFrom;
66  
67      // ----------------/
68      // - Constructors -/
69      // ----------------/
70  
71      public InputLocation(org.apache.maven.api.model.InputLocation location) {
72          this.lineNumber = location.getLineNumber();
73          this.columnNumber = location.getColumnNumber();
74          this.source = location.getSource() != null ? new InputSource(location.getSource()) : null;
75          this.locations = location.getLocations().isEmpty()
76                  ? null
77                  : location.getLocations().entrySet().stream()
78                          .collect(Collectors.toMap(
79                                  e -> e.getKey(),
80                                  e -> e.getValue() == location ? this : new InputLocation(e.getValue())));
81          this.importedFrom = location.getImportedFrom() != null ? new InputLocation(location.getImportedFrom()) : null;
82      }
83  
84      public InputLocation(int lineNumber, int columnNumber) {
85          this.lineNumber = lineNumber;
86          this.columnNumber = columnNumber;
87      } // -- org.apache.maven.model.InputLocation(int, int)
88  
89      public InputLocation(int lineNumber, int columnNumber, InputSource source) {
90          this.lineNumber = lineNumber;
91          this.columnNumber = columnNumber;
92          this.source = source;
93      } // -- org.apache.maven.model.InputLocation(int, int, InputSource)
94  
95      // -----------/
96      // - Methods -/
97      // -----------/
98  
99      /**
100      * Method clone.
101      *
102      * @return InputLocation
103      */
104     public InputLocation clone() {
105         try {
106             InputLocation copy = (InputLocation) super.clone();
107 
108             if (copy.locations != null) {
109                 copy.locations = new java.util.LinkedHashMap(copy.locations);
110             }
111 
112             return copy;
113         } catch (Exception ex) {
114             throw (RuntimeException)
115                     new UnsupportedOperationException(getClass().getName() + " does not support clone()").initCause(ex);
116         }
117     } // -- InputLocation clone()
118 
119     /**
120      * Get the one-based column number. The value will be
121      * non-positive if unknown.
122      *
123      * @return int
124      */
125     public int getColumnNumber() {
126         return this.columnNumber;
127     } // -- int getColumnNumber()
128 
129     /**
130      * Get the one-based line number. The value will be
131      * non-positive if unknown.
132      *
133      * @return int
134      */
135     public int getLineNumber() {
136         return this.lineNumber;
137     } // -- int getLineNumber()
138 
139     /**
140      *
141      *
142      * @param key
143      * @return InputLocation
144      */
145     @Override
146     public InputLocation getLocation(Object key) {
147         if (key instanceof String string) {
148             switch (string) {
149                 case "": {
150                     return this.location;
151                 }
152                 default: {
153                     return getOtherLocation(key);
154                 }
155             }
156         } else {
157             return getOtherLocation(key);
158         }
159     } // -- InputLocation getLocation( Object )
160 
161     /**
162      *
163      *
164      * @return Map
165      */
166     public java.util.Map<Object, InputLocation> getLocations() {
167         return locations;
168     } // -- java.util.Map<Object, InputLocation> getLocations()
169 
170     /**
171      *
172      *
173      * @param key
174      * @param location
175      */
176     @Override
177     public void setLocation(Object key, InputLocation location) {
178         if (key instanceof String string) {
179             switch (string) {
180                 case "": {
181                     this.location = location;
182                     return;
183                 }
184                 default: {
185                     setOtherLocation(key, location);
186                     return;
187                 }
188             }
189         } else {
190             setOtherLocation(key, location);
191         }
192     } // -- void setLocation( Object, InputLocation )
193 
194     /**
195      *
196      *
197      * @param key
198      * @param location
199      */
200     public void setOtherLocation(Object key, InputLocation location) {
201         if (location != null) {
202             if (this.locations == null) {
203                 this.locations = new java.util.LinkedHashMap<>();
204             }
205             this.locations.put(key, location);
206         }
207     } // -- void setOtherLocation( Object, InputLocation )
208 
209     /**
210      *
211      *
212      * @param key
213      * @return InputLocation
214      */
215     private InputLocation getOtherLocation(Object key) {
216         return (locations != null) ? locations.get(key) : null;
217     } // -- InputLocation getOtherLocation( Object )
218 
219     /**
220      * Get the source field.
221      *
222      * @return InputSource
223      */
224     public InputSource getSource() {
225         return this.source;
226     } // -- InputSource getSource()
227 
228     /**
229      * Gets the parent InputLocation where this InputLocation may have been imported from.
230      * Can return {@code null}.
231      *
232      * @return InputLocation
233      * @since 4.0.0
234      */
235     public InputLocation getImportedFrom() {
236         return importedFrom;
237     }
238 
239     /**
240      * Set the imported from location.
241      *
242      * @param importedFrom
243      */
244     public void setImportedFrom(InputLocation importedFrom) {
245         this.importedFrom = importedFrom;
246     }
247 
248     /**
249      * Method merge.
250      *
251      * @param target
252      * @param sourceDominant
253      * @param source
254      * @return InputLocation
255      */
256     public static InputLocation merge(InputLocation target, InputLocation source, boolean sourceDominant) {
257         if (source == null) {
258             return target;
259         } else if (target == null) {
260             return source;
261         }
262 
263         InputLocation result = new InputLocation(target.getLineNumber(), target.getColumnNumber(), target.getSource());
264 
265         java.util.Map<Object, InputLocation> locations;
266         java.util.Map<Object, InputLocation> sourceLocations = source.getLocations();
267         java.util.Map<Object, InputLocation> targetLocations = target.getLocations();
268         if (sourceLocations == null) {
269             locations = targetLocations;
270         } else if (targetLocations == null) {
271             locations = sourceLocations;
272         } else {
273             locations = new java.util.LinkedHashMap();
274             locations.putAll(sourceDominant ? targetLocations : sourceLocations);
275             locations.putAll(sourceDominant ? sourceLocations : targetLocations);
276         }
277         result.setLocations(locations);
278 
279         return result;
280     } // -- InputLocation merge( InputLocation, InputLocation, boolean )
281 
282     /**
283      * Method merge.
284      *
285      * @param target
286      * @param indices
287      * @param source
288      * @return InputLocation
289      */
290     public static InputLocation merge(
291             InputLocation target, InputLocation source, java.util.Collection<Integer> indices) {
292         if (source == null) {
293             return target;
294         } else if (target == null) {
295             return source;
296         }
297 
298         InputLocation result = new InputLocation(target.getLineNumber(), target.getColumnNumber(), target.getSource());
299 
300         java.util.Map<Object, InputLocation> locations;
301         java.util.Map<Object, InputLocation> sourceLocations = source.getLocations();
302         java.util.Map<Object, InputLocation> targetLocations = target.getLocations();
303         if (sourceLocations == null) {
304             locations = targetLocations;
305         } else if (targetLocations == null) {
306             locations = sourceLocations;
307         } else {
308             locations = new java.util.LinkedHashMap<>();
309             for (java.util.Iterator<Integer> it = indices.iterator(); it.hasNext(); ) {
310                 InputLocation location;
311                 Integer index = it.next();
312                 if (index.intValue() < 0) {
313                     location = sourceLocations.get(Integer.valueOf(~index.intValue()));
314                 } else {
315                     location = targetLocations.get(index);
316                 }
317                 locations.put(Integer.valueOf(locations.size()), location);
318             }
319         }
320         result.setLocations(locations);
321 
322         return result;
323     } // -- InputLocation merge( InputLocation, InputLocation, java.util.Collection )
324 
325     /**
326      *
327      *
328      * @param locations
329      */
330     public void setLocations(java.util.Map<Object, InputLocation> locations) {
331         this.locations = locations;
332     } // -- void setLocations( java.util.Map )
333 
334     public org.apache.maven.api.model.InputLocation toApiLocation() {
335         if (locations != null && locations.values().contains(this)) {
336             if (locations.size() == 1 && locations.values().iterator().next() == this) {
337                 return new org.apache.maven.api.model.InputLocation(
338                         lineNumber,
339                         columnNumber,
340                         source != null ? source.toApiSource() : null,
341                         locations.keySet().iterator().next());
342             } else {
343                 return new org.apache.maven.api.model.InputLocation(
344                         lineNumber, columnNumber, source != null ? source.toApiSource() : null);
345             }
346         } else {
347             return new org.apache.maven.api.model.InputLocation(
348                     lineNumber,
349                     columnNumber,
350                     source != null ? source.toApiSource() : null,
351                     locations != null
352                             ? locations.entrySet().stream().collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue()
353                                     .toApiLocation()))
354                             : null);
355         }
356     }
357 
358     // -----------------/
359     // - Inner Classes -/
360     // -----------------/
361 
362     /**
363      * Class StringFormatter.
364      *
365      * @version $Revision$ $Date$
366      */
367     public abstract static class StringFormatter {
368 
369         // -----------/
370         // - Methods -/
371         // -----------/
372 
373         /**
374          * Method toString.
375          *
376          * @param location
377          * @return String
378          */
379         public abstract String toString(InputLocation location);
380     }
381 
382     @Override
383     public String toString() {
384         return getLineNumber() + " : " + getColumnNumber() + ", " + getSource();
385     }
386 }