1*d57664e9SAndroid Build Coastguard Worker /* 2*d57664e9SAndroid Build Coastguard Worker * Copyright (C) 2015 The Android Open Source Project 3*d57664e9SAndroid Build Coastguard Worker * 4*d57664e9SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License"); 5*d57664e9SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License. 6*d57664e9SAndroid Build Coastguard Worker * You may obtain a copy of the License at 7*d57664e9SAndroid Build Coastguard Worker * 8*d57664e9SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0 9*d57664e9SAndroid Build Coastguard Worker * 10*d57664e9SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software 11*d57664e9SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS, 12*d57664e9SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*d57664e9SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and 14*d57664e9SAndroid Build Coastguard Worker * limitations under the License. 15*d57664e9SAndroid Build Coastguard Worker */ 16*d57664e9SAndroid Build Coastguard Worker 17*d57664e9SAndroid Build Coastguard Worker #ifndef AAPT_JAVA_CLASSDEFINITION_H 18*d57664e9SAndroid Build Coastguard Worker #define AAPT_JAVA_CLASSDEFINITION_H 19*d57664e9SAndroid Build Coastguard Worker 20*d57664e9SAndroid Build Coastguard Worker #include <string> 21*d57664e9SAndroid Build Coastguard Worker #include <unordered_map> 22*d57664e9SAndroid Build Coastguard Worker #include <vector> 23*d57664e9SAndroid Build Coastguard Worker 24*d57664e9SAndroid Build Coastguard Worker #include "android-base/macros.h" 25*d57664e9SAndroid Build Coastguard Worker #include "androidfw/StringPiece.h" 26*d57664e9SAndroid Build Coastguard Worker 27*d57664e9SAndroid Build Coastguard Worker #include "Resource.h" 28*d57664e9SAndroid Build Coastguard Worker #include "java/AnnotationProcessor.h" 29*d57664e9SAndroid Build Coastguard Worker #include "text/Printer.h" 30*d57664e9SAndroid Build Coastguard Worker #include "util/Util.h" 31*d57664e9SAndroid Build Coastguard Worker 32*d57664e9SAndroid Build Coastguard Worker namespace aapt { 33*d57664e9SAndroid Build Coastguard Worker 34*d57664e9SAndroid Build Coastguard Worker // The number of attributes to emit per line in a Styleable array. 35*d57664e9SAndroid Build Coastguard Worker constexpr static size_t kAttribsPerLine = 4; 36*d57664e9SAndroid Build Coastguard Worker constexpr static const char* kIndent = " "; 37*d57664e9SAndroid Build Coastguard Worker 38*d57664e9SAndroid Build Coastguard Worker class ClassMember { 39*d57664e9SAndroid Build Coastguard Worker public: 40*d57664e9SAndroid Build Coastguard Worker virtual ~ClassMember() = default; 41*d57664e9SAndroid Build Coastguard Worker GetCommentBuilder()42*d57664e9SAndroid Build Coastguard Worker AnnotationProcessor* GetCommentBuilder() { 43*d57664e9SAndroid Build Coastguard Worker return &processor_; 44*d57664e9SAndroid Build Coastguard Worker } 45*d57664e9SAndroid Build Coastguard Worker 46*d57664e9SAndroid Build Coastguard Worker virtual bool empty() const = 0; 47*d57664e9SAndroid Build Coastguard Worker 48*d57664e9SAndroid Build Coastguard Worker virtual const std::string& GetName() const = 0; 49*d57664e9SAndroid Build Coastguard Worker 50*d57664e9SAndroid Build Coastguard Worker // Writes the class member to the Printer. Subclasses should derive this method 51*d57664e9SAndroid Build Coastguard Worker // to write their own data. Call this base method from the subclass to write out 52*d57664e9SAndroid Build Coastguard Worker // this member's comments/annotations. 53*d57664e9SAndroid Build Coastguard Worker virtual void Print(bool final, text::Printer* printer, bool strip_api_annotations = false) const; 54*d57664e9SAndroid Build Coastguard Worker 55*d57664e9SAndroid Build Coastguard Worker private: 56*d57664e9SAndroid Build Coastguard Worker AnnotationProcessor processor_; 57*d57664e9SAndroid Build Coastguard Worker }; 58*d57664e9SAndroid Build Coastguard Worker 59*d57664e9SAndroid Build Coastguard Worker template <typename T> 60*d57664e9SAndroid Build Coastguard Worker class PrimitiveMember : public ClassMember { 61*d57664e9SAndroid Build Coastguard Worker public: 62*d57664e9SAndroid Build Coastguard Worker PrimitiveMember(android::StringPiece name, const T& val, bool staged_api = false) name_(name)63*d57664e9SAndroid Build Coastguard Worker : name_(name), val_(val), staged_api_(staged_api) { 64*d57664e9SAndroid Build Coastguard Worker } 65*d57664e9SAndroid Build Coastguard Worker empty()66*d57664e9SAndroid Build Coastguard Worker bool empty() const override { 67*d57664e9SAndroid Build Coastguard Worker return false; 68*d57664e9SAndroid Build Coastguard Worker } 69*d57664e9SAndroid Build Coastguard Worker GetName()70*d57664e9SAndroid Build Coastguard Worker const std::string& GetName() const override { 71*d57664e9SAndroid Build Coastguard Worker return name_; 72*d57664e9SAndroid Build Coastguard Worker } 73*d57664e9SAndroid Build Coastguard Worker 74*d57664e9SAndroid Build Coastguard Worker void Print(bool final, text::Printer* printer, 75*d57664e9SAndroid Build Coastguard Worker bool strip_api_annotations = false) const override { 76*d57664e9SAndroid Build Coastguard Worker using std::to_string; 77*d57664e9SAndroid Build Coastguard Worker 78*d57664e9SAndroid Build Coastguard Worker ClassMember::Print(final, printer, strip_api_annotations); 79*d57664e9SAndroid Build Coastguard Worker 80*d57664e9SAndroid Build Coastguard Worker printer->Print("public static "); 81*d57664e9SAndroid Build Coastguard Worker if (final) { 82*d57664e9SAndroid Build Coastguard Worker printer->Print("final "); 83*d57664e9SAndroid Build Coastguard Worker } 84*d57664e9SAndroid Build Coastguard Worker printer->Print("int ").Print(name_); 85*d57664e9SAndroid Build Coastguard Worker if (staged_api_) { 86*d57664e9SAndroid Build Coastguard Worker // Prevent references to staged apis from being inline by setting their value out-of-line. 87*d57664e9SAndroid Build Coastguard Worker printer->Print("; static { ").Print(name_); 88*d57664e9SAndroid Build Coastguard Worker } 89*d57664e9SAndroid Build Coastguard Worker printer->Print("=").Print(to_string(val_)).Print(";"); 90*d57664e9SAndroid Build Coastguard Worker if (staged_api_) { 91*d57664e9SAndroid Build Coastguard Worker printer->Print(" }"); 92*d57664e9SAndroid Build Coastguard Worker } 93*d57664e9SAndroid Build Coastguard Worker } 94*d57664e9SAndroid Build Coastguard Worker 95*d57664e9SAndroid Build Coastguard Worker private: 96*d57664e9SAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(PrimitiveMember); 97*d57664e9SAndroid Build Coastguard Worker 98*d57664e9SAndroid Build Coastguard Worker std::string name_; 99*d57664e9SAndroid Build Coastguard Worker T val_; 100*d57664e9SAndroid Build Coastguard Worker bool staged_api_; 101*d57664e9SAndroid Build Coastguard Worker }; 102*d57664e9SAndroid Build Coastguard Worker 103*d57664e9SAndroid Build Coastguard Worker // Specialization for strings so they get the right type and are quoted with "". 104*d57664e9SAndroid Build Coastguard Worker template <> 105*d57664e9SAndroid Build Coastguard Worker class PrimitiveMember<std::string> : public ClassMember { 106*d57664e9SAndroid Build Coastguard Worker public: 107*d57664e9SAndroid Build Coastguard Worker PrimitiveMember(android::StringPiece name, const std::string& val, bool staged_api = false) name_(name)108*d57664e9SAndroid Build Coastguard Worker : name_(name), val_(val) { 109*d57664e9SAndroid Build Coastguard Worker } 110*d57664e9SAndroid Build Coastguard Worker empty()111*d57664e9SAndroid Build Coastguard Worker bool empty() const override { 112*d57664e9SAndroid Build Coastguard Worker return false; 113*d57664e9SAndroid Build Coastguard Worker } 114*d57664e9SAndroid Build Coastguard Worker GetName()115*d57664e9SAndroid Build Coastguard Worker const std::string& GetName() const override { 116*d57664e9SAndroid Build Coastguard Worker return name_; 117*d57664e9SAndroid Build Coastguard Worker } 118*d57664e9SAndroid Build Coastguard Worker 119*d57664e9SAndroid Build Coastguard Worker void Print(bool final, text::Printer* printer, bool strip_api_annotations = false) 120*d57664e9SAndroid Build Coastguard Worker const override { 121*d57664e9SAndroid Build Coastguard Worker ClassMember::Print(final, printer, strip_api_annotations); 122*d57664e9SAndroid Build Coastguard Worker 123*d57664e9SAndroid Build Coastguard Worker printer->Print("public static "); 124*d57664e9SAndroid Build Coastguard Worker if (final) { 125*d57664e9SAndroid Build Coastguard Worker printer->Print("final "); 126*d57664e9SAndroid Build Coastguard Worker } 127*d57664e9SAndroid Build Coastguard Worker printer->Print("String ").Print(name_).Print("=\"").Print(val_).Print("\";"); 128*d57664e9SAndroid Build Coastguard Worker } 129*d57664e9SAndroid Build Coastguard Worker 130*d57664e9SAndroid Build Coastguard Worker private: 131*d57664e9SAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(PrimitiveMember); 132*d57664e9SAndroid Build Coastguard Worker 133*d57664e9SAndroid Build Coastguard Worker std::string name_; 134*d57664e9SAndroid Build Coastguard Worker std::string val_; 135*d57664e9SAndroid Build Coastguard Worker }; 136*d57664e9SAndroid Build Coastguard Worker 137*d57664e9SAndroid Build Coastguard Worker using IntMember = PrimitiveMember<uint32_t>; 138*d57664e9SAndroid Build Coastguard Worker using ResourceMember = PrimitiveMember<ResourceId>; 139*d57664e9SAndroid Build Coastguard Worker using StringMember = PrimitiveMember<std::string>; 140*d57664e9SAndroid Build Coastguard Worker 141*d57664e9SAndroid Build Coastguard Worker template <typename T, typename StringConverter> 142*d57664e9SAndroid Build Coastguard Worker class PrimitiveArrayMember : public ClassMember { 143*d57664e9SAndroid Build Coastguard Worker public: PrimitiveArrayMember(android::StringPiece name)144*d57664e9SAndroid Build Coastguard Worker explicit PrimitiveArrayMember(android::StringPiece name) : name_(name) { 145*d57664e9SAndroid Build Coastguard Worker } 146*d57664e9SAndroid Build Coastguard Worker AddElement(const T & val)147*d57664e9SAndroid Build Coastguard Worker void AddElement(const T& val) { 148*d57664e9SAndroid Build Coastguard Worker elements_.emplace_back(val); 149*d57664e9SAndroid Build Coastguard Worker } 150*d57664e9SAndroid Build Coastguard Worker empty()151*d57664e9SAndroid Build Coastguard Worker bool empty() const override { 152*d57664e9SAndroid Build Coastguard Worker return false; 153*d57664e9SAndroid Build Coastguard Worker } 154*d57664e9SAndroid Build Coastguard Worker GetName()155*d57664e9SAndroid Build Coastguard Worker const std::string& GetName() const override { 156*d57664e9SAndroid Build Coastguard Worker return name_; 157*d57664e9SAndroid Build Coastguard Worker } 158*d57664e9SAndroid Build Coastguard Worker 159*d57664e9SAndroid Build Coastguard Worker void Print(bool final, text::Printer* printer, bool strip_api_annotations = false) 160*d57664e9SAndroid Build Coastguard Worker const override { 161*d57664e9SAndroid Build Coastguard Worker ClassMember::Print(final, printer, strip_api_annotations); 162*d57664e9SAndroid Build Coastguard Worker 163*d57664e9SAndroid Build Coastguard Worker printer->Print("public static final int[] ").Print(name_).Print("={"); 164*d57664e9SAndroid Build Coastguard Worker printer->Indent(); 165*d57664e9SAndroid Build Coastguard Worker 166*d57664e9SAndroid Build Coastguard Worker const auto begin = elements_.begin(); 167*d57664e9SAndroid Build Coastguard Worker const auto end = elements_.end(); 168*d57664e9SAndroid Build Coastguard Worker for (auto current = begin; current != end; ++current) { 169*d57664e9SAndroid Build Coastguard Worker if (std::distance(begin, current) % kAttribsPerLine == 0) { 170*d57664e9SAndroid Build Coastguard Worker printer->Println(); 171*d57664e9SAndroid Build Coastguard Worker } 172*d57664e9SAndroid Build Coastguard Worker 173*d57664e9SAndroid Build Coastguard Worker printer->Print(StringConverter::ToString(*current)); 174*d57664e9SAndroid Build Coastguard Worker if (std::distance(current, end) > 1) { 175*d57664e9SAndroid Build Coastguard Worker printer->Print(", "); 176*d57664e9SAndroid Build Coastguard Worker } 177*d57664e9SAndroid Build Coastguard Worker } 178*d57664e9SAndroid Build Coastguard Worker printer->Println(); 179*d57664e9SAndroid Build Coastguard Worker printer->Undent(); 180*d57664e9SAndroid Build Coastguard Worker printer->Print("};"); 181*d57664e9SAndroid Build Coastguard Worker } 182*d57664e9SAndroid Build Coastguard Worker 183*d57664e9SAndroid Build Coastguard Worker private: 184*d57664e9SAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(PrimitiveArrayMember); 185*d57664e9SAndroid Build Coastguard Worker 186*d57664e9SAndroid Build Coastguard Worker std::string name_; 187*d57664e9SAndroid Build Coastguard Worker std::vector<T> elements_; 188*d57664e9SAndroid Build Coastguard Worker }; 189*d57664e9SAndroid Build Coastguard Worker 190*d57664e9SAndroid Build Coastguard Worker struct FieldReference { FieldReferenceFieldReference191*d57664e9SAndroid Build Coastguard Worker explicit FieldReference(std::string reference) : ref(std::move(reference)) { 192*d57664e9SAndroid Build Coastguard Worker } 193*d57664e9SAndroid Build Coastguard Worker std::string ref; 194*d57664e9SAndroid Build Coastguard Worker }; 195*d57664e9SAndroid Build Coastguard Worker 196*d57664e9SAndroid Build Coastguard Worker struct ResourceArrayMemberStringConverter { ToStringResourceArrayMemberStringConverter197*d57664e9SAndroid Build Coastguard Worker static std::string ToString(const std::variant<ResourceId, FieldReference>& ref) { 198*d57664e9SAndroid Build Coastguard Worker if (auto id = std::get_if<ResourceId>(&ref)) { 199*d57664e9SAndroid Build Coastguard Worker return to_string(*id); 200*d57664e9SAndroid Build Coastguard Worker } else { 201*d57664e9SAndroid Build Coastguard Worker return std::get<FieldReference>(ref).ref; 202*d57664e9SAndroid Build Coastguard Worker } 203*d57664e9SAndroid Build Coastguard Worker } 204*d57664e9SAndroid Build Coastguard Worker }; 205*d57664e9SAndroid Build Coastguard Worker 206*d57664e9SAndroid Build Coastguard Worker using ResourceArrayMember = PrimitiveArrayMember<std::variant<ResourceId, FieldReference>, 207*d57664e9SAndroid Build Coastguard Worker ResourceArrayMemberStringConverter>; 208*d57664e9SAndroid Build Coastguard Worker 209*d57664e9SAndroid Build Coastguard Worker // Represents a method in a class. 210*d57664e9SAndroid Build Coastguard Worker class MethodDefinition : public ClassMember { 211*d57664e9SAndroid Build Coastguard Worker public: 212*d57664e9SAndroid Build Coastguard Worker // Expected method signature example: 'public static void onResourcesLoaded(int p)'. MethodDefinition(android::StringPiece signature)213*d57664e9SAndroid Build Coastguard Worker explicit MethodDefinition(android::StringPiece signature) : signature_(signature) { 214*d57664e9SAndroid Build Coastguard Worker } 215*d57664e9SAndroid Build Coastguard Worker 216*d57664e9SAndroid Build Coastguard Worker // Appends a single statement to the method. It should include no newlines or else 217*d57664e9SAndroid Build Coastguard Worker // formatting may be broken. 218*d57664e9SAndroid Build Coastguard Worker void AppendStatement(android::StringPiece statement); 219*d57664e9SAndroid Build Coastguard Worker 220*d57664e9SAndroid Build Coastguard Worker // Not quite the same as a name, but good enough. GetName()221*d57664e9SAndroid Build Coastguard Worker const std::string& GetName() const override { 222*d57664e9SAndroid Build Coastguard Worker return signature_; 223*d57664e9SAndroid Build Coastguard Worker } 224*d57664e9SAndroid Build Coastguard Worker 225*d57664e9SAndroid Build Coastguard Worker // Even if the method is empty, we always want to write the method signature. empty()226*d57664e9SAndroid Build Coastguard Worker bool empty() const override { 227*d57664e9SAndroid Build Coastguard Worker return false; 228*d57664e9SAndroid Build Coastguard Worker } 229*d57664e9SAndroid Build Coastguard Worker 230*d57664e9SAndroid Build Coastguard Worker void Print(bool final, text::Printer* printer, bool strip_api_annotations = false) const override; 231*d57664e9SAndroid Build Coastguard Worker 232*d57664e9SAndroid Build Coastguard Worker private: 233*d57664e9SAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(MethodDefinition); 234*d57664e9SAndroid Build Coastguard Worker 235*d57664e9SAndroid Build Coastguard Worker std::string signature_; 236*d57664e9SAndroid Build Coastguard Worker std::vector<std::string> statements_; 237*d57664e9SAndroid Build Coastguard Worker }; 238*d57664e9SAndroid Build Coastguard Worker 239*d57664e9SAndroid Build Coastguard Worker enum class ClassQualifier { kNone, kStatic }; 240*d57664e9SAndroid Build Coastguard Worker 241*d57664e9SAndroid Build Coastguard Worker class ClassDefinition : public ClassMember { 242*d57664e9SAndroid Build Coastguard Worker public: 243*d57664e9SAndroid Build Coastguard Worker static void WriteJavaFile(const ClassDefinition* def, android::StringPiece package, bool final, 244*d57664e9SAndroid Build Coastguard Worker bool strip_api_annotations, android::OutputStream* out); 245*d57664e9SAndroid Build Coastguard Worker ClassDefinition(android::StringPiece name,ClassQualifier qualifier,bool createIfEmpty)246*d57664e9SAndroid Build Coastguard Worker ClassDefinition(android::StringPiece name, ClassQualifier qualifier, bool createIfEmpty) 247*d57664e9SAndroid Build Coastguard Worker : name_(name), qualifier_(qualifier), create_if_empty_(createIfEmpty) { 248*d57664e9SAndroid Build Coastguard Worker } 249*d57664e9SAndroid Build Coastguard Worker 250*d57664e9SAndroid Build Coastguard Worker enum class Result { 251*d57664e9SAndroid Build Coastguard Worker kAdded, 252*d57664e9SAndroid Build Coastguard Worker kOverridden, 253*d57664e9SAndroid Build Coastguard Worker }; 254*d57664e9SAndroid Build Coastguard Worker 255*d57664e9SAndroid Build Coastguard Worker Result AddMember(std::unique_ptr<ClassMember> member); 256*d57664e9SAndroid Build Coastguard Worker 257*d57664e9SAndroid Build Coastguard Worker bool empty() const override; 258*d57664e9SAndroid Build Coastguard Worker GetName()259*d57664e9SAndroid Build Coastguard Worker const std::string& GetName() const override { 260*d57664e9SAndroid Build Coastguard Worker return name_; 261*d57664e9SAndroid Build Coastguard Worker } 262*d57664e9SAndroid Build Coastguard Worker 263*d57664e9SAndroid Build Coastguard Worker void Print(bool final, text::Printer* printer, bool strip_api_annotations = false) const override; 264*d57664e9SAndroid Build Coastguard Worker 265*d57664e9SAndroid Build Coastguard Worker private: 266*d57664e9SAndroid Build Coastguard Worker DISALLOW_COPY_AND_ASSIGN(ClassDefinition); 267*d57664e9SAndroid Build Coastguard Worker 268*d57664e9SAndroid Build Coastguard Worker std::string name_; 269*d57664e9SAndroid Build Coastguard Worker ClassQualifier qualifier_; 270*d57664e9SAndroid Build Coastguard Worker bool create_if_empty_; 271*d57664e9SAndroid Build Coastguard Worker std::vector<std::unique_ptr<ClassMember>> ordered_members_; 272*d57664e9SAndroid Build Coastguard Worker std::unordered_map<android::StringPiece, size_t> indexed_members_; 273*d57664e9SAndroid Build Coastguard Worker }; 274*d57664e9SAndroid Build Coastguard Worker 275*d57664e9SAndroid Build Coastguard Worker } // namespace aapt 276*d57664e9SAndroid Build Coastguard Worker 277*d57664e9SAndroid Build Coastguard Worker #endif /* AAPT_JAVA_CLASSDEFINITION_H */ 278