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 32namespace aapt { 33 34// The number of attributes to emit per line in a Styleable array. 35constexpr static size_t kAttribsPerLine = 4; 36constexpr static const char* kIndent = " "; 37 38class ClassMember { 39 public: 40 virtual ~ClassMember() = default; 41 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 59template <typename T> 60class PrimitiveMember : public ClassMember { 61 public: 62 PrimitiveMember(const android::StringPiece& name, const T& val) 63 : name_(name.to_string()), val_(val) {} 64 65 bool empty() const override { 66 return false; 67 } 68 69 const std::string& GetName() const override { 70 return name_; 71 } 72 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 "". 93template <> 94class PrimitiveMember<std::string> : public ClassMember { 95 public: 96 PrimitiveMember(const android::StringPiece& name, const std::string& val) 97 : name_(name.to_string()), val_(val) {} 98 99 bool empty() const override { 100 return false; 101 } 102 103 const std::string& GetName() const override { 104 return name_; 105 } 106 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 124using IntMember = PrimitiveMember<uint32_t>; 125using ResourceMember = PrimitiveMember<ResourceId>; 126using StringMember = PrimitiveMember<std::string>; 127 128template <typename T> 129class PrimitiveArrayMember : public ClassMember { 130 public: 131 explicit PrimitiveArrayMember(const android::StringPiece& name) : name_(name.to_string()) {} 132 133 void AddElement(const T& val) { 134 elements_.push_back(val); 135 } 136 137 bool empty() const override { 138 return false; 139 } 140 141 const std::string& GetName() const override { 142 return name_; 143 } 144 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 175using ResourceArrayMember = PrimitiveArrayMember<ResourceId>; 176 177// Represents a method in a class. 178class MethodDefinition : public ClassMember { 179 public: 180 // Expected method signature example: 'public static void onResourcesLoaded(int p)'. 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. 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. 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 207enum class ClassQualifier { kNone, kStatic }; 208 209class ClassDefinition : public ClassMember { 210 public: 211 static void WriteJavaFile(const ClassDefinition* def, const android::StringPiece& package, 212 bool final, io::OutputStream* out); 213 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 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