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 30namespace aapt { 31 32// The number of attributes to emit per line in a Styleable array. 33constexpr static size_t kAttribsPerLine = 4; 34constexpr static const char* kIndent = " "; 35 36class ClassMember { 37 public: 38 virtual ~ClassMember() = default; 39 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 54template <typename T> 55class PrimitiveMember : public ClassMember { 56 public: 57 PrimitiveMember(const android::StringPiece& name, const T& val) 58 : name_(name.to_string()), val_(val) {} 59 60 bool empty() const override { return false; } 61 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 */ 80template <> 81class PrimitiveMember<std::string> : public ClassMember { 82 public: 83 PrimitiveMember(const android::StringPiece& name, const std::string& val) 84 : name_(name.to_string()), val_(val) {} 85 86 bool empty() const override { return false; } 87 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 103using IntMember = PrimitiveMember<uint32_t>; 104using ResourceMember = PrimitiveMember<ResourceId>; 105using StringMember = PrimitiveMember<std::string>; 106 107template <typename T> 108class PrimitiveArrayMember : public ClassMember { 109 public: 110 explicit PrimitiveArrayMember(const android::StringPiece& name) : name_(name.to_string()) {} 111 112 void AddElement(const T& val) { elements_.push_back(val); } 113 114 bool empty() const override { return false; } 115 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 144using ResourceArrayMember = PrimitiveArrayMember<ResourceId>; 145 146// Represents a method in a class. 147class MethodDefinition : public ClassMember { 148 public: 149 // Expected method signature example: 'public static void onResourcesLoaded(int p)'. 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. 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 168enum class ClassQualifier { kNone, kStatic }; 169 170class ClassDefinition : public ClassMember { 171 public: 172 static bool WriteJavaFile(const ClassDefinition* def, const android::StringPiece& package, 173 bool final, std::ostream* out); 174 175 ClassDefinition(const android::StringPiece& name, ClassQualifier qualifier, bool createIfEmpty) 176 : name_(name.to_string()), qualifier_(qualifier), create_if_empty_(createIfEmpty) {} 177 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