1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef AAPT_JAVA_CLASSDEFINITION_H
18 #define AAPT_JAVA_CLASSDEFINITION_H
19 
20 #include <string>
21 #include <unordered_map>
22 #include <vector>
23 
24 #include "android-base/macros.h"
25 #include "androidfw/StringPiece.h"
26 
27 #include "Resource.h"
28 #include "java/AnnotationProcessor.h"
29 #include "text/Printer.h"
30 #include "util/Util.h"
31 
32 namespace aapt {
33 
34 // The number of attributes to emit per line in a Styleable array.
35 constexpr static size_t kAttribsPerLine = 4;
36 constexpr static const char* kIndent = "  ";
37 
38 class ClassMember {
39  public:
40   virtual ~ClassMember() = default;
41 
GetCommentBuilder()42   AnnotationProcessor* GetCommentBuilder() {
43     return &processor_;
44   }
45 
46   virtual bool empty() const = 0;
47 
48   virtual const std::string& GetName() const = 0;
49 
50   // Writes the class member to the Printer. Subclasses should derive this method
51   // to write their own data. Call this base method from the subclass to write out
52   // this member's comments/annotations.
53   virtual void Print(bool final, text::Printer* printer, bool strip_api_annotations = false) const;
54 
55  private:
56   AnnotationProcessor processor_;
57 };
58 
59 template <typename T>
60 class PrimitiveMember : public ClassMember {
61  public:
PrimitiveMember(const android::StringPiece & name,const T & val)62   PrimitiveMember(const android::StringPiece& name, const T& val)
63       : name_(name.to_string()), val_(val) {}
64 
empty()65   bool empty() const override {
66     return false;
67   }
68 
GetName()69   const std::string& GetName() const override {
70     return name_;
71   }
72 
73   void Print(bool final, text::Printer* printer, bool strip_api_annotations = false)
74       const override {
75     using std::to_string;
76 
77     ClassMember::Print(final, printer, strip_api_annotations);
78 
79     printer->Print("public static ");
80     if (final) {
81       printer->Print("final ");
82     }
83     printer->Print("int ").Print(name_).Print("=").Print(to_string(val_)).Print(";");
84   }
85 
86  private:
87   DISALLOW_COPY_AND_ASSIGN(PrimitiveMember);
88 
89   std::string name_;
90   T val_;
91 };
92 
93 // Specialization for strings so they get the right type and are quoted with "".
94 template <>
95 class PrimitiveMember<std::string> : public ClassMember {
96  public:
PrimitiveMember(const android::StringPiece & name,const std::string & val)97   PrimitiveMember(const android::StringPiece& name, const std::string& val)
98       : name_(name.to_string()), val_(val) {}
99 
empty()100   bool empty() const override {
101     return false;
102   }
103 
GetName()104   const std::string& GetName() const override {
105     return name_;
106   }
107 
108   void Print(bool final, text::Printer* printer, bool strip_api_annotations = false)
109       const override {
110     ClassMember::Print(final, printer, strip_api_annotations);
111 
112     printer->Print("public static ");
113     if (final) {
114       printer->Print("final ");
115     }
116     printer->Print("String ").Print(name_).Print("=\"").Print(val_).Print("\";");
117   }
118 
119  private:
120   DISALLOW_COPY_AND_ASSIGN(PrimitiveMember);
121 
122   std::string name_;
123   std::string val_;
124 };
125 
126 using IntMember = PrimitiveMember<uint32_t>;
127 using ResourceMember = PrimitiveMember<ResourceId>;
128 using StringMember = PrimitiveMember<std::string>;
129 
130 template <typename T>
131 class PrimitiveArrayMember : public ClassMember {
132  public:
PrimitiveArrayMember(const android::StringPiece & name)133   explicit PrimitiveArrayMember(const android::StringPiece& name) : name_(name.to_string()) {}
134 
AddElement(const T & val)135   void AddElement(const T& val) {
136     elements_.push_back(val);
137   }
138 
empty()139   bool empty() const override {
140     return false;
141   }
142 
GetName()143   const std::string& GetName() const override {
144     return name_;
145   }
146 
147   void Print(bool final, text::Printer* printer, bool strip_api_annotations = false)
148       const override {
149     ClassMember::Print(final, printer, strip_api_annotations);
150 
151     printer->Print("public static final int[] ").Print(name_).Print("={");
152     printer->Indent();
153 
154     const auto begin = elements_.begin();
155     const auto end = elements_.end();
156     for (auto current = begin; current != end; ++current) {
157       if (std::distance(begin, current) % kAttribsPerLine == 0) {
158         printer->Println();
159       }
160 
161       printer->Print(to_string(*current));
162       if (std::distance(current, end) > 1) {
163         printer->Print(", ");
164       }
165     }
166     printer->Println();
167     printer->Undent();
168     printer->Print("};");
169   }
170 
171  private:
172   DISALLOW_COPY_AND_ASSIGN(PrimitiveArrayMember);
173 
174   std::string name_;
175   std::vector<T> elements_;
176 };
177 
178 using ResourceArrayMember = PrimitiveArrayMember<ResourceId>;
179 
180 // Represents a method in a class.
181 class MethodDefinition : public ClassMember {
182  public:
183   // Expected method signature example: 'public static void onResourcesLoaded(int p)'.
MethodDefinition(const android::StringPiece & signature)184   explicit MethodDefinition(const android::StringPiece& signature)
185       : signature_(signature.to_string()) {}
186 
187   // Appends a single statement to the method. It should include no newlines or else
188   // formatting may be broken.
189   void AppendStatement(const android::StringPiece& statement);
190 
191   // Not quite the same as a name, but good enough.
GetName()192   const std::string& GetName() const override {
193     return signature_;
194   }
195 
196   // Even if the method is empty, we always want to write the method signature.
empty()197   bool empty() const override {
198     return false;
199   }
200 
201   void Print(bool final, text::Printer* printer, bool strip_api_annotations = false) const override;
202 
203  private:
204   DISALLOW_COPY_AND_ASSIGN(MethodDefinition);
205 
206   std::string signature_;
207   std::vector<std::string> statements_;
208 };
209 
210 enum class ClassQualifier { kNone, kStatic };
211 
212 class ClassDefinition : public ClassMember {
213  public:
214   static void WriteJavaFile(const ClassDefinition* def, const android::StringPiece& package,
215                             bool final, bool strip_api_annotations, io::OutputStream* out);
216 
ClassDefinition(const android::StringPiece & name,ClassQualifier qualifier,bool createIfEmpty)217   ClassDefinition(const android::StringPiece& name, ClassQualifier qualifier, bool createIfEmpty)
218       : name_(name.to_string()), qualifier_(qualifier), create_if_empty_(createIfEmpty) {}
219 
220   enum class Result {
221     kAdded,
222     kOverridden,
223   };
224 
225   Result AddMember(std::unique_ptr<ClassMember> member);
226 
227   bool empty() const override;
228 
GetName()229   const std::string& GetName() const override {
230     return name_;
231   }
232 
233   void Print(bool final, text::Printer* printer, bool strip_api_annotations = false) const override;
234 
235  private:
236   DISALLOW_COPY_AND_ASSIGN(ClassDefinition);
237 
238   std::string name_;
239   ClassQualifier qualifier_;
240   bool create_if_empty_;
241   std::vector<std::unique_ptr<ClassMember>> ordered_members_;
242   std::unordered_map<android::StringPiece, size_t> indexed_members_;
243 };
244 
245 }  // namespace aapt
246 
247 #endif /* AAPT_JAVA_CLASSDEFINITION_H */
248