• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package com.android.class2nonsdklist;
2 
3 import com.android.annotationvisitor.AnnotationConsumer;
4 
5 import java.io.File;
6 import java.io.FileNotFoundException;
7 import java.io.FileOutputStream;
8 import java.io.OutputStream;
9 import java.io.PrintStream;
10 import java.util.ArrayList;
11 import java.util.Comparator;
12 import java.util.HashMap;
13 import java.util.HashSet;
14 import java.util.List;
15 import java.util.Map;
16 import java.util.Set;
17 import java.util.stream.Collectors;
18 
19 public class AnnotationPropertyWriter implements AnnotationConsumer {
20 
21     private static final String SIGNATURE_COLUMN = "signature";
22     private final PrintStream mOutput;
23     private final List<Map<String, String>> mContents;
24     private final Set<String> mColumns;
25 
AnnotationPropertyWriter(String csvFile)26     public AnnotationPropertyWriter(String csvFile) throws FileNotFoundException {
27         mOutput = new PrintStream(new FileOutputStream(new File(csvFile)));
28         mContents = new ArrayList<>();
29         mColumns = new HashSet<>();
30     }
31 
AnnotationPropertyWriter(OutputStream output)32     public AnnotationPropertyWriter(OutputStream output) {
33         mOutput = new PrintStream(output);
34         mContents = new ArrayList<>();
35         mColumns = new HashSet<>();
36     }
37 
consume(String apiSignature, Map<String, String> annotationProperties, Set<String> parsedFlags)38     public void consume(String apiSignature, Map<String, String> annotationProperties,
39             Set<String> parsedFlags) {
40         // Clone properties map.
41         Map<String, String> contents = new HashMap<>(annotationProperties);
42 
43         // Append the member signature.
44         contents.put(SIGNATURE_COLUMN, apiSignature);
45 
46         // Store data.
47         mColumns.addAll(contents.keySet());
48         mContents.add(contents);
49     }
50 
escapeCsvColumn(String column)51     private static String escapeCsvColumn(String column) {
52         // Using '|' as a quote character, as in frameworks/base/tools/hiddenapi/merge_csv.py
53         // Escape '|' characters in the column, then wrap the column in '|' characters.
54         column = column.replace("|", "||");
55         return "|" + column + "|";
56     }
57 
close()58     public void close() {
59         // Sort columns by name.
60         List<String> columns = new ArrayList<>(mColumns);
61         columns.sort(Comparator.naturalOrder());
62 
63         // Make sure that the signature column, if present, comes first.
64         if (columns.remove(SIGNATURE_COLUMN)) {
65             columns.add(0, SIGNATURE_COLUMN);
66         }
67 
68         // Print header row.
69         mOutput.println(String.join(",", columns));
70 
71         // Sort rows by signature
72         mContents.sort(Comparator.comparing(r -> r.get(SIGNATURE_COLUMN)));
73 
74         // Print contents of each row in column order.
75         for (Map<String, String> row : mContents) {
76             mOutput.println(columns.stream().map(column -> row.getOrDefault(column, ""))
77                 .map(AnnotationPropertyWriter::escapeCsvColumn)
78                 .collect(Collectors.joining(",")));
79         }
80 
81         // Close output.
82         mOutput.close();
83     }
84 }
85