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.settings;
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      @Override
79      public InputLocation getLocation(Object key) {
80          return locations != null ? locations.get(key) : null;
81      }
82  
83      public Map<Object, InputLocation> getLocations() {
84          return locations;
85      }
86  
87      /**
88       * Merges the {@code source} location into the {@code target} location.
89       *
90       * @param target the target location
91       * @param source the source location
92       * @param sourceDominant the boolean indicating of {@code source} is dominant compared to {@code target}
93       * @return the merged location
94       */
95      public static InputLocation merge(InputLocation target, InputLocation source, boolean sourceDominant) {
96          if (source == null) {
97              return target;
98          } else if (target == null) {
99              return source;
100         }
101 
102         Map<Object, InputLocation> locations;
103         Map<Object, InputLocation> sourceLocations = source.locations;
104         Map<Object, InputLocation> targetLocations = target.locations;
105         if (sourceLocations == null) {
106             locations = targetLocations;
107         } else if (targetLocations == null) {
108             locations = sourceLocations;
109         } else {
110             locations = new LinkedHashMap<>();
111             locations.putAll(sourceDominant ? targetLocations : sourceLocations);
112             locations.putAll(sourceDominant ? sourceLocations : targetLocations);
113         }
114 
115         return new InputLocation(target.getLineNumber(), target.getColumnNumber(), target.getSource(), locations);
116     } // -- InputLocation merge( InputLocation, InputLocation, boolean )
117 
118     /**
119      * Merges the {@code source} location into the {@code target} location.
120      * This method is used when the locations refer to lists and also merges the indices.
121      *
122      * @param target the target location
123      * @param source the source location
124      * @param indices the list of integers for the indices
125      * @return the merged location
126      */
127     public static InputLocation merge(InputLocation target, InputLocation source, Collection<Integer> indices) {
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             for (int index : indices) {
144                 InputLocation location;
145                 if (index < 0) {
146                     location = sourceLocations.get(~index);
147                 } else {
148                     location = targetLocations.get(index);
149                 }
150                 locations.put(locations.size(), location);
151             }
152         }
153 
154         return new InputLocation(target.getLineNumber(), target.getColumnNumber(), target.getSource(), locations);
155     } // -- InputLocation merge( InputLocation, InputLocation, java.util.Collection )
156 
157     /**
158      * Class StringFormatter.
159      *
160      * @version $Revision$ $Date$
161      */
162     public interface StringFormatter {
163 
164         // -----------/
165         // - Methods -/
166         // -----------/
167 
168         /**
169          * Method toString.
170          */
171         String toString(InputLocation location);
172     }
173 }