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  
20  package org.apache.rat.report.claim;
21  
22  import java.util.ArrayList;
23  import java.util.Comparator;
24  import java.util.List;
25  import java.util.Locale;
26  import java.util.concurrent.ConcurrentHashMap;
27  
28  import org.apache.commons.lang3.StringUtils;
29  import org.apache.rat.api.Document;
30  
31  /**
32   * This class provides a numerical overview about
33   * the report.
34   */
35  public class ClaimStatistic {
36      // keep the counter types in alphabetical order
37      /** The counter types */
38      public enum Counter {
39          /** count of approved files */
40          APPROVED("A count of approved licenses.", -1, 0),
41          /** count of archive files */
42          ARCHIVES("A count of archive files.", -1, 0),
43          /** count of binary  files */
44          BINARIES("A count of binary files.", -1, 0),
45          /** count of distinct document types */
46          DOCUMENT_TYPES("A count of distinct document types.", -1, 1),
47          /** count of generated/ignored files */
48          IGNORED("A count of ignored files.", -1, 0),
49          /** count of license categories */
50          LICENSE_CATEGORIES("A count of distinct license categories.", -1, 1),
51          /** count of distinct license names */
52          LICENSE_NAMES("A count of distinct license names.", -1, 1),
53          /** count of note files */
54          NOTICES("A count of notice files.", -1, 0),
55          /** count of standard files */
56          STANDARDS("A count of standard files.", -1, 1),
57          /** count of unapproved files */
58          UNAPPROVED("A count of unapproved licenses.", 0, 0),
59          /** count of unknown files */
60          UNKNOWN("A count of unknown file types.", -1, 0);
61  
62          /** The description of the counter */
63          private final String description;
64          /** The default max value for the counter */
65          private final int defaultMaxValue;
66          /** The default minimum value for the counter */
67          private final int defaultMinValue;
68  
69          Counter(final String description, final int defaultMaxValue, final int defaultMinValue) {
70              this.description = description;
71              this.defaultMaxValue = defaultMaxValue;
72              this.defaultMinValue = defaultMinValue;
73          }
74  
75          /**
76           * Gets the description of the counter.
77           * @return The description of the counter.
78           */
79          public String getDescription() {
80              return description;
81          }
82  
83          /**
84           * Gets the default maximum value for the counter.
85           * @return the default maximum value for the counter.
86           */
87          public int getDefaultMaxValue() {
88              return defaultMaxValue;
89          }
90          /**
91           * Gets the default minimum value for the counter.
92           * @return the default maximum value for the counter.
93           */
94          public int getDefaultMinValue() {
95              return defaultMinValue;
96          }
97  
98          /**
99           * Display name is capitalized and any underscores are replaced by spaces.
100          * @return displayName of the counter, capitalized and without underscores.
101          */
102         public String displayName() {
103             return StringUtils.capitalize(name().replaceAll("_", " ").toLowerCase(Locale.ROOT));
104         }
105     }
106 
107     /** Count of license family name to counter */
108     private final ConcurrentHashMap<String, IntCounter> licenseNameMap = new ConcurrentHashMap<>();
109     /** Map of license family category to counter */
110     private final ConcurrentHashMap<String, IntCounter> licenseFamilyCategoryMap = new ConcurrentHashMap<>();
111     /** Map of document type to counter */
112     private final ConcurrentHashMap<Document.Type, IntCounter> documentTypeMap = new ConcurrentHashMap<>();
113     /** Map of counter type to value */
114     private final ConcurrentHashMap<ClaimStatistic.Counter, IntCounter> counterMap = new ConcurrentHashMap<>();
115 
116     /**
117      * Converts null counter to 0.
118      *
119      * @param counter the Counter to retrieve the value from.
120      * @return 0 if counter is {@code null} or counter value otherwise.
121      */
122     private int getValue(final IntCounter counter) {
123         return counter == null ? 0 : counter.value();
124     }
125 
126     /**
127      * Returns the counts for the counter.
128      * @param counter the counter to get the value for.
129      * @return the number times the counter type was seen.
130      */
131     public int getCounter(final Counter counter) {
132         return getValue(counterMap.get(counter));
133     }
134 
135     /**
136      * Increments the counts for the counter.
137      * @param counter the counter to increment.
138      * @param value the value to increment the counter by.
139      */
140     public void incCounter(final Counter counter, final int value) {
141         counterMap.compute(counter, (k, v) -> v == null ? new IntCounter().increment(value) : v.increment(value));
142     }
143 
144     /**
145      * Gets the counts for the Document.Type.
146      * @param documentType the Document.Type to get the counter for.
147      * @return the number times the Document.Type was seen.
148      */
149     public int getCounter(final Document.Type documentType) {
150         return getValue(documentTypeMap.get(documentType));
151     }
152 
153     /**
154      * Gets the set of Document.Types seen in the run.
155      * @return the set of Document.Types seen in the run.
156      */
157     public List<Document.Type> getDocumentTypes() {
158         List<Document.Type> result = new ArrayList<>(documentTypeMap.keySet());
159         result.sort(Comparator.comparing(Enum::name));
160         return result;
161     }
162 
163     /**
164      * Increments the number of times the Document.Type was seen.
165      * @param documentType the Document.Type to increment.
166      * @param value the value to increment the counter by.
167      */
168     public void incCounter(final Document.Type documentType, final int value) {
169         documentTypeMap.compute(documentType, (k, v) -> updateCounter(Counter.DOCUMENT_TYPES, v, value));
170         switch (documentType) {
171             case STANDARD:
172                 incCounter(Counter.STANDARDS, value);
173                 break;
174             case ARCHIVE:
175                 incCounter(Counter.ARCHIVES, value);
176                 break;
177             case BINARY:
178                 incCounter(Counter.BINARIES, value);
179                 break;
180             case NOTICE:
181                 incCounter(Counter.NOTICES, value);
182                 break;
183             case UNKNOWN:
184                 incCounter(Counter.UNKNOWN, value);
185                 break;
186             case IGNORED:
187                 incCounter(Counter.IGNORED, value);
188                 break;
189         }
190     }
191 
192     /**
193      * Gets the counts for the license category.
194      * @param licenseFamilyCategory the license family category to get the count for.
195      * @return the number of times the license family category was seen.
196      */
197     public int getLicenseCategoryCount(final String licenseFamilyCategory) {
198         return getValue(licenseFamilyCategoryMap.get(licenseFamilyCategory));
199     }
200 
201     /**
202      * Gets the counts for the license name.
203      * @param licenseName the license name to get the count for.
204      * @return the number of times the license family category was seen.
205      */
206     public int getLicenseNameCount(final String licenseName) {
207         return getValue(licenseNameMap.get(licenseName));
208     }
209 
210     /**
211      * Updates the intCounter with the value and if the intCounter was null creates a new one and registers the
212      * creation as a counter type.
213      * @param counter the Type of the counter.
214      * @param intCounter the IntCounter to update. May be null.
215      * @param value the value to add to the int counter.
216      * @return the intCounter if it was not {@code null}, a new IntCounter otherwise.
217      */
218     private IntCounter updateCounter(final Counter counter, final IntCounter intCounter, final int value) {
219         if (intCounter == null) {
220             incCounter(counter, 1);
221             return new IntCounter().increment(value);
222         } else {
223             return intCounter.increment(value);
224         }
225     }
226 
227     /**
228      * Increments the number of times a license family category was seen.
229      * @param licenseFamilyCategory the License family category to increment.
230      * @param value the value to increment the count by.
231      */
232     public void incLicenseCategoryCount(final String licenseFamilyCategory, final int value) {
233         licenseFamilyCategoryMap.compute(licenseFamilyCategory, (k, v) -> updateCounter(Counter.LICENSE_CATEGORIES, v, value));
234     }
235 
236     /**
237      * Gets the set of license family categories that were seen.
238      * @return A set of license family categories.
239      */
240     public List<String> getLicenseFamilyCategories() {
241         List<String> result = new ArrayList<>(licenseFamilyCategoryMap.keySet());
242         result.sort(String::compareTo);
243         return result;
244     }
245 
246     /**
247      * Gets the license names sorted by name.
248      * @return sorted list of license names.
249      */
250     public List<String> getLicenseNames() {
251         List<String> result = new ArrayList<>(licenseNameMap.keySet());
252         result.sort(String::compareTo);
253         return result;
254     }
255 
256     /**
257      * Increments the license family name count.
258      * @param licenseName the license name to increment.
259      * @param value the value to increment the count by.
260      */
261     public void incLicenseNameCount(final String licenseName, final int value) {
262         licenseNameMap.compute(licenseName, (k, v) -> updateCounter(Counter.LICENSE_NAMES, v, value));
263     }
264 
265     /**
266      * A class that wraps an int and allows easy increment and retrieval.
267      */
268     static class IntCounter {
269         /**
270          * The value of the counter
271          */
272         private int value;
273 
274         /**
275          * Increment the count.
276          * @param count the count to increment by (can be negative).
277          * @return this.
278          */
279         public IntCounter increment(final int count) {
280             value += count;
281             return this;
282         }
283 
284         /**
285          * Retrieves the count.
286          * @return the count contained by this counter.
287          */
288         public int value() {
289             return value;
290         }
291     }
292 }