• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <ostream>
21 #include <string>
22 #include <unordered_map>
23 #include <vector>
24 
25 #include "android-base/macros.h"
26 #include "androidfw/StringPiece.h"
27 
28 #include "Resource.h"
29 #include "java/AnnotationProcessor.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 out stream. 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 WriteToStream(const android::StringPiece& prefix, bool final,
54                              std::ostream* out) const;
55 
56  private:
57   AnnotationProcessor processor_;
58 };
59 
60 template <typename T>
61 class PrimitiveMember : public ClassMember {
62  public:
PrimitiveMember(const android::StringPiece & name,const T & val)63   PrimitiveMember(const android::StringPiece& name, const T& val)
64       : name_(name.to_string()), val_(val) {}
65 
empty()66   bool empty() const override {
67     return false;
68   }
69 
GetName()70   const std::string& GetName() const override {
71     return name_;
72   }
73 
WriteToStream(const android::StringPiece & prefix,bool final,std::ostream * out)74   void WriteToStream(const android::StringPiece& prefix, bool final,
75                      std::ostream* out) const override {
76     ClassMember::WriteToStream(prefix, final, out);
77     *out << prefix << "public static " << (final ? "final " : "") << "int " << name_ << "=" << val_
78          << ";";
79   }
80 
81  private:
82   DISALLOW_COPY_AND_ASSIGN(PrimitiveMember);
83 
84   std::string name_;
85   T val_;
86 };
87 
88 // Specialization for strings so they get the right type and are quoted with "".
89 template <>
90 class PrimitiveMember<std::string> : public ClassMember {
91  public:
PrimitiveMember(const android::StringPiece & name,const std::string & val)92   PrimitiveMember(const android::StringPiece& name, const std::string& val)
93       : name_(name.to_string()), val_(val) {}
94 
empty()95   bool empty() const override {
96     return false;
97   }
98 
GetName()99   const std::string& GetName() const override {
100     return name_;
101   }
102 
WriteToStream(const android::StringPiece & prefix,bool final,std::ostream * out)103   void WriteToStream(const android::StringPiece& prefix, bool final,
104                      std::ostream* out) const override {
105     ClassMember::WriteToStream(prefix, final, out);
106 
107     *out << prefix << "public static " << (final ? "final " : "") << "String "
108          << name_ << "=\"" << val_ << "\";";
109   }
110 
111  private:
112   DISALLOW_COPY_AND_ASSIGN(PrimitiveMember);
113 
114   std::string name_;
115   std::string val_;
116 };
117 
118 using IntMember = PrimitiveMember<uint32_t>;
119 using ResourceMember = PrimitiveMember<ResourceId>;
120 using StringMember = PrimitiveMember<std::string>;
121 
122 template <typename T>
123 class PrimitiveArrayMember : public ClassMember {
124  public:
PrimitiveArrayMember(const android::StringPiece & name)125   explicit PrimitiveArrayMember(const android::StringPiece& name) : name_(name.to_string()) {}
126 
AddElement(const T & val)127   void AddElement(const T& val) {
128     elements_.push_back(val);
129   }
130 
empty()131   bool empty() const override {
132     return false;
133   }
134 
GetName()135   const std::string& GetName() const override {
136     return name_;
137   }
138 
WriteToStream(const android::StringPiece & prefix,bool final,std::ostream * out)139   void WriteToStream(const android::StringPiece& prefix, bool final,
140                      std::ostream* out) const override {
141     ClassMember::WriteToStream(prefix, final, out);
142 
143     *out << prefix << "public static final int[] " << name_ << "={";
144 
145     const auto begin = elements_.begin();
146     const auto end = elements_.end();
147     for (auto current = begin; current != end; ++current) {
148       if (std::distance(begin, current) % kAttribsPerLine == 0) {
149         *out << "\n" << prefix << kIndent << kIndent;
150       }
151 
152       *out << *current;
153       if (std::distance(current, end) > 1) {
154         *out << ", ";
155       }
156     }
157     *out << "\n" << prefix << kIndent << "};";
158   }
159 
160  private:
161   DISALLOW_COPY_AND_ASSIGN(PrimitiveArrayMember);
162 
163   std::string name_;
164   std::vector<T> elements_;
165 };
166 
167 using ResourceArrayMember = PrimitiveArrayMember<ResourceId>;
168 
169 // Represents a method in a class.
170 class MethodDefinition : public ClassMember {
171  public:
172   // Expected method signature example: 'public static void onResourcesLoaded(int p)'.
MethodDefinition(const android::StringPiece & signature)173   explicit MethodDefinition(const android::StringPiece& signature)
174       : signature_(signature.to_string()) {}
175 
176   // Appends a single statement to the method. It should include no newlines or else
177   // formatting may be broken.
178   void AppendStatement(const android::StringPiece& statement);
179 
180   // Not quite the same as a name, but good enough.
GetName()181   const std::string& GetName() const override {
182     return signature_;
183   }
184 
185   // Even if the method is empty, we always want to write the method signature.
empty()186   bool empty() const override {
187     return false;
188   }
189 
190   void WriteToStream(const android::StringPiece& prefix, bool final,
191                      std::ostream* out) const override;
192 
193  private:
194   DISALLOW_COPY_AND_ASSIGN(MethodDefinition);
195 
196   std::string signature_;
197   std::vector<std::string> statements_;
198 };
199 
200 enum class ClassQualifier { kNone, kStatic };
201 
202 class ClassDefinition : public ClassMember {
203  public:
204   static bool WriteJavaFile(const ClassDefinition* def, const android::StringPiece& package,
205                             bool final, std::ostream* out);
206 
ClassDefinition(const android::StringPiece & name,ClassQualifier qualifier,bool createIfEmpty)207   ClassDefinition(const android::StringPiece& name, ClassQualifier qualifier, bool createIfEmpty)
208       : name_(name.to_string()), qualifier_(qualifier), create_if_empty_(createIfEmpty) {}
209 
210   enum class Result {
211     kAdded,
212     kOverridden,
213   };
214 
215   Result AddMember(std::unique_ptr<ClassMember> member);
216 
217   bool empty() const override;
218 
GetName()219   const std::string& GetName() const override {
220     return name_;
221   }
222 
223   void WriteToStream(const android::StringPiece& prefix, bool final,
224                      std::ostream* out) const override;
225 
226  private:
227   DISALLOW_COPY_AND_ASSIGN(ClassDefinition);
228 
229   std::string name_;
230   ClassQualifier qualifier_;
231   bool create_if_empty_;
232   std::vector<std::unique_ptr<ClassMember>> ordered_members_;
233   std::unordered_map<android::StringPiece, size_t> indexed_members_;
234 };
235 
236 }  // namespace aapt
237 
238 #endif /* AAPT_JAVA_CLASSDEFINITION_H */
239