Home | History | Annotate | Download | only in java
      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 
     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 
     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 
     59 template <typename T>
     60 class 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 "".
     93 template <>
     94 class 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 
    124 using IntMember = PrimitiveMember<uint32_t>;
    125 using ResourceMember = PrimitiveMember<ResourceId>;
    126 using StringMember = PrimitiveMember<std::string>;
    127 
    128 template <typename T>
    129 class 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 
    175 using ResourceArrayMember = PrimitiveArrayMember<ResourceId>;
    176 
    177 // Represents a method in a class.
    178 class 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 
    207 enum class ClassQualifier { kNone, kStatic };
    208 
    209 class 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