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