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 <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 
     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:
     63   PrimitiveMember(const android::StringPiece& name, const T& val)
     64       : name_(name.to_string()), val_(val) {}
     65 
     66   bool empty() const override {
     67     return false;
     68   }
     69 
     70   const std::string& GetName() const override {
     71     return name_;
     72   }
     73 
     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:
     92   PrimitiveMember(const android::StringPiece& name, const std::string& val)
     93       : name_(name.to_string()), val_(val) {}
     94 
     95   bool empty() const override {
     96     return false;
     97   }
     98 
     99   const std::string& GetName() const override {
    100     return name_;
    101   }
    102 
    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:
    125   explicit PrimitiveArrayMember(const android::StringPiece& name) : name_(name.to_string()) {}
    126 
    127   void AddElement(const T& val) {
    128     elements_.push_back(val);
    129   }
    130 
    131   bool empty() const override {
    132     return false;
    133   }
    134 
    135   const std::string& GetName() const override {
    136     return name_;
    137   }
    138 
    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)'.
    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.
    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.
    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 
    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 
    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