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