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.api.toolchain;
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  
27  /**
28   * Class InputLocation.
29   */
30  public class InputLocation implements Serializable, InputLocationTracker {
31      private final int lineNumber;
32      private final int columnNumber;
33      private final InputSource source;
34      private final Map<Object, InputLocation> locations;
35  
36      public InputLocation(InputSource source) {
37          this.lineNumber = -1;
38          this.columnNumber = -1;
39          this.source = source;
40          this.locations = Collections.singletonMap(0, this);
41      }
42  
43      public InputLocation(int lineNumber, int columnNumber) {
44          this(lineNumber, columnNumber, null, null);
45      }
46  
47      public InputLocation(int lineNumber, int columnNumber, InputSource source) {
48          this(lineNumber, columnNumber, source, null);
49      }
50  
51      public InputLocation(int lineNumber, int columnNumber, InputSource source, Object selfLocationKey) {
52          this.lineNumber = lineNumber;
53          this.columnNumber = columnNumber;
54          this.source = source;
55          this.locations =
56                  selfLocationKey != null ? Collections.singletonMap(selfLocationKey, this) : Collections.emptyMap();
57      }
58  
59      public InputLocation(int lineNumber, int columnNumber, InputSource source, Map<Object, InputLocation> locations) {
60          this.lineNumber = lineNumber;
61          this.columnNumber = columnNumber;
62          this.source = source;
63          this.locations = ImmutableCollections.copy(locations);
64      }
65  
66      public int getLineNumber() {
67          return lineNumber;
68      }
69  
70      public int getColumnNumber() {
71          return columnNumber;
72      }
73  
74      public InputSource getSource() {
75          return source;
76      }
77  
78      public InputLocation getLocation(Object key) {
79          return locations != null ? locations.get(key) : null;
80      }
81  
82      public Map<Object, InputLocation> getLocations() {
83          return locations;
84      }
85  
86      /**
87       * Merges the {@code source} location into the {@code target} location.
88       *
89       * @param target the target location
90       * @param source the source location
91       * @param sourceDominant the boolean indicating of {@code source} is dominant compared to {@code target}
92       * @return the merged location
93       */
94      public static InputLocation merge(InputLocation target, InputLocation source, boolean sourceDominant) {
95          if (source == null) {
96              return target;
97          } else if (target == null) {
98              return source;
99          }
100 
101         Map<Object, InputLocation> locations;
102         Map<Object, InputLocation> sourceLocations = source.locations;
103         Map<Object, InputLocation> targetLocations = target.locations;
104         if (sourceLocations == null) {
105             locations = targetLocations;
106         } else if (targetLocations == null) {
107             locations = sourceLocations;
108         } else {
109             locations = new LinkedHashMap<>();
110             locations.putAll(sourceDominant ? targetLocations : sourceLocations);
111             locations.putAll(sourceDominant ? sourceLocations : targetLocations);
112         }
113 
114         return new InputLocation(target.getLineNumber(), target.getColumnNumber(), target.getSource(), locations);
115     } // -- InputLocation merge( InputLocation, InputLocation, boolean )
116 
117     /**
118      * Merges the {@code source} location into the {@code target} location.
119      * This method is used when the locations refer to lists and also merges the indices.
120      *
121      * @param target the target location
122      * @param source the source location
123      * @param indices the list of integers for the indices
124      * @return the merged location
125      */
126     public static InputLocation merge(InputLocation target, InputLocation source, Collection<Integer> indices) {
127         if (source == null) {
128             return target;
129         } else if (target == null) {
130             return source;
131         }
132 
133         Map<Object, InputLocation> locations;
134         Map<Object, InputLocation> sourceLocations = source.locations;
135         Map<Object, InputLocation> targetLocations = target.locations;
136         if (sourceLocations == null) {
137             locations = targetLocations;
138         } else if (targetLocations == null) {
139             locations = sourceLocations;
140         } else {
141             locations = new LinkedHashMap<>();
142             for (int index : indices) {
143                 InputLocation location;
144                 if (index < 0) {
145                     location = sourceLocations.get(~index);
146                 } else {
147                     location = targetLocations.get(index);
148                 }
149                 locations.put(locations.size(), location);
150             }
151         }
152 
153         return new InputLocation(target.getLineNumber(), target.getColumnNumber(), target.getSource(), locations);
154     } // -- InputLocation merge( InputLocation, InputLocation, java.util.Collection )
155 
156     /**
157      * Class StringFormatter.
158      *
159      * @version $Revision$ $Date$
160      */
161     public interface StringFormatter {
162 
163         // -----------/
164         // - Methods -/
165         // -----------/
166 
167         /**
168          * Method toString.
169          */
170         String toString(InputLocation location);
171     }
172 }