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 23 #include "android-base/macros.h" 24 #include "androidfw/StringPiece.h" 25 26 #include "Resource.h" 27 #include "java/AnnotationProcessor.h" 28 #include "util/Util.h" 29 30 namespace aapt { 31 32 // The number of attributes to emit per line in a Styleable array. 33 constexpr static size_t kAttribsPerLine = 4; 34 constexpr static const char* kIndent = " "; 35 36 class ClassMember { 37 public: 38 virtual ~ClassMember() = default; 39 GetCommentBuilder()40 AnnotationProcessor* GetCommentBuilder() { return &processor_; } 41 42 virtual bool empty() const = 0; 43 44 // Writes the class member to the out stream. Subclasses should derive this method 45 // to write their own data. Call this base method from the subclass to write out 46 // this member's comments/annotations. 47 virtual void WriteToStream(const android::StringPiece& prefix, bool final, 48 std::ostream* out) const; 49 50 private: 51 AnnotationProcessor processor_; 52 }; 53 54 template <typename T> 55 class PrimitiveMember : public ClassMember { 56 public: PrimitiveMember(const android::StringPiece & name,const T & val)57 PrimitiveMember(const android::StringPiece& name, const T& val) 58 : name_(name.to_string()), val_(val) {} 59 empty()60 bool empty() const override { return false; } 61 WriteToStream(const android::StringPiece & prefix,bool final,std::ostream * out)62 void WriteToStream(const android::StringPiece& prefix, bool final, 63 std::ostream* out) const override { 64 ClassMember::WriteToStream(prefix, final, out); 65 66 *out << prefix << "public static " << (final ? "final " : "") << "int " 67 << name_ << "=" << val_ << ";"; 68 } 69 70 private: 71 std::string name_; 72 T val_; 73 74 DISALLOW_COPY_AND_ASSIGN(PrimitiveMember); 75 }; 76 77 /** 78 * Specialization for strings so they get the right type and are quoted with "". 79 */ 80 template <> 81 class PrimitiveMember<std::string> : public ClassMember { 82 public: PrimitiveMember(const android::StringPiece & name,const std::string & val)83 PrimitiveMember(const android::StringPiece& name, const std::string& val) 84 : name_(name.to_string()), val_(val) {} 85 empty()86 bool empty() const override { return false; } 87 WriteToStream(const android::StringPiece & prefix,bool final,std::ostream * out)88 void WriteToStream(const android::StringPiece& prefix, bool final, 89 std::ostream* out) const override { 90 ClassMember::WriteToStream(prefix, final, out); 91 92 *out << prefix << "public static " << (final ? "final " : "") << "String " 93 << name_ << "=\"" << val_ << "\";"; 94 } 95 96 private: 97 std::string name_; 98 std::string val_; 99 100 DISALLOW_COPY_AND_ASSIGN(PrimitiveMember); 101 }; 102 103 using IntMember = PrimitiveMember<uint32_t>; 104 using ResourceMember = PrimitiveMember<ResourceId>; 105 using StringMember = PrimitiveMember<std::string>; 106 107 template <typename T> 108 class PrimitiveArrayMember : public ClassMember { 109 public: PrimitiveArrayMember(const android::StringPiece & name)110 explicit PrimitiveArrayMember(const android::StringPiece& name) : name_(name.to_string()) {} 111 AddElement(const T & val)112 void AddElement(const T& val) { elements_.push_back(val); } 113 empty()114 bool empty() const override { return false; } 115 WriteToStream(const android::StringPiece & prefix,bool final,std::ostream * out)116 void WriteToStream(const android::StringPiece& prefix, bool final, 117 std::ostream* out) const override { 118 ClassMember::WriteToStream(prefix, final, out); 119 120 *out << prefix << "public static final int[] " << name_ << "={"; 121 122 const auto begin = elements_.begin(); 123 const auto end = elements_.end(); 124 for (auto current = begin; current != end; ++current) { 125 if (std::distance(begin, current) % kAttribsPerLine == 0) { 126 *out << "\n" << prefix << kIndent << kIndent; 127 } 128 129 *out << *current; 130 if (std::distance(current, end) > 1) { 131 *out << ", "; 132 } 133 } 134 *out << "\n" << prefix << kIndent << "};"; 135 } 136 137 private: 138 std::string name_; 139 std::vector<T> elements_; 140 141 DISALLOW_COPY_AND_ASSIGN(PrimitiveArrayMember); 142 }; 143 144 using ResourceArrayMember = PrimitiveArrayMember<ResourceId>; 145 146 // Represents a method in a class. 147 class MethodDefinition : public ClassMember { 148 public: 149 // Expected method signature example: 'public static void onResourcesLoaded(int p)'. MethodDefinition(const android::StringPiece & signature)150 explicit MethodDefinition(const android::StringPiece& signature) 151 : signature_(signature.to_string()) {} 152 153 // Appends a single statement to the method. It should include no newlines or else 154 // formatting may be broken. 155 void AppendStatement(const android::StringPiece& statement); 156 157 // Even if the method is empty, we always want to write the method signature. empty()158 bool empty() const override { return false; } 159 160 void WriteToStream(const android::StringPiece& prefix, bool final, 161 std::ostream* out) const override; 162 163 private: 164 std::string signature_; 165 std::vector<std::string> statements_; 166 }; 167 168 enum class ClassQualifier { kNone, kStatic }; 169 170 class ClassDefinition : public ClassMember { 171 public: 172 static bool WriteJavaFile(const ClassDefinition* def, const android::StringPiece& package, 173 bool final, std::ostream* out); 174 ClassDefinition(const android::StringPiece & name,ClassQualifier qualifier,bool createIfEmpty)175 ClassDefinition(const android::StringPiece& name, ClassQualifier qualifier, bool createIfEmpty) 176 : name_(name.to_string()), qualifier_(qualifier), create_if_empty_(createIfEmpty) {} 177 AddMember(std::unique_ptr<ClassMember> member)178 void AddMember(std::unique_ptr<ClassMember> member) { 179 members_.push_back(std::move(member)); 180 } 181 182 bool empty() const override; 183 void WriteToStream(const android::StringPiece& prefix, bool final, 184 std::ostream* out) const override; 185 186 private: 187 std::string name_; 188 ClassQualifier qualifier_; 189 bool create_if_empty_; 190 std::vector<std::unique_ptr<ClassMember>> members_; 191 192 DISALLOW_COPY_AND_ASSIGN(ClassDefinition); 193 }; 194 195 } // namespace aapt 196 197 #endif /* AAPT_JAVA_CLASSDEFINITION_H */ 198