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_TEST_BUILDERS_H
18#define AAPT_TEST_BUILDERS_H
19
20#include "ResourceTable.h"
21#include "ResourceValues.h"
22#include "test/Common.h"
23#include "util/Util.h"
24#include "xml/XmlDom.h"
25
26#include <memory>
27
28namespace aapt {
29namespace test {
30
31class ResourceTableBuilder {
32private:
33    DummyDiagnosticsImpl mDiagnostics;
34    std::unique_ptr<ResourceTable> mTable = util::make_unique<ResourceTable>();
35
36public:
37    ResourceTableBuilder() = default;
38
39    StringPool* getStringPool() {
40        return &mTable->stringPool;
41    }
42
43    ResourceTableBuilder& setPackageId(const StringPiece16& packageName, uint8_t id) {
44        ResourceTablePackage* package = mTable->createPackage(packageName, id);
45        assert(package);
46        return *this;
47    }
48
49    ResourceTableBuilder& addSimple(const StringPiece16& name, const ResourceId id = {}) {
50        return addValue(name, id, util::make_unique<Id>());
51    }
52
53    ResourceTableBuilder& addReference(const StringPiece16& name, const StringPiece16& ref) {
54        return addReference(name, {}, ref);
55    }
56
57    ResourceTableBuilder& addReference(const StringPiece16& name, const ResourceId id,
58                                       const StringPiece16& ref) {
59        return addValue(name, id, util::make_unique<Reference>(parseNameOrDie(ref)));
60    }
61
62    ResourceTableBuilder& addString(const StringPiece16& name, const StringPiece16& str) {
63        return addString(name, {}, str);
64    }
65
66    ResourceTableBuilder& addString(const StringPiece16& name, const ResourceId id,
67                                    const StringPiece16& str) {
68        return addValue(name, id, util::make_unique<String>(mTable->stringPool.makeRef(str)));
69    }
70
71    ResourceTableBuilder& addString(const StringPiece16& name, const ResourceId id,
72                                    const ConfigDescription& config, const StringPiece16& str) {
73        return addValue(name, id, config,
74                        util::make_unique<String>(mTable->stringPool.makeRef(str)));
75    }
76
77    ResourceTableBuilder& addFileReference(const StringPiece16& name, const StringPiece16& path) {
78        return addFileReference(name, {}, path);
79    }
80
81    ResourceTableBuilder& addFileReference(const StringPiece16& name, const ResourceId id,
82                                           const StringPiece16& path) {
83        return addValue(name, id,
84                        util::make_unique<FileReference>(mTable->stringPool.makeRef(path)));
85    }
86
87    ResourceTableBuilder& addFileReference(const StringPiece16& name, const StringPiece16& path,
88                                           const ConfigDescription& config) {
89        return addValue(name, {}, config,
90                        util::make_unique<FileReference>(mTable->stringPool.makeRef(path)));
91    }
92
93    ResourceTableBuilder& addValue(const StringPiece16& name,
94                                   std::unique_ptr<Value> value) {
95        return addValue(name, {}, std::move(value));
96    }
97
98    ResourceTableBuilder& addValue(const StringPiece16& name, const ResourceId id,
99                                       std::unique_ptr<Value> value) {
100        return addValue(name, id, {}, std::move(value));
101    }
102
103    ResourceTableBuilder& addValue(const StringPiece16& name, const ResourceId id,
104                                   const ConfigDescription& config,
105                                   std::unique_ptr<Value> value) {
106        ResourceName resName = parseNameOrDie(name);
107        bool result = mTable->addResourceAllowMangled(resName, id, config, std::string(),
108                                                      std::move(value), &mDiagnostics);
109        assert(result);
110        return *this;
111    }
112
113    ResourceTableBuilder& setSymbolState(const StringPiece16& name, ResourceId id,
114                                         SymbolState state) {
115        ResourceName resName = parseNameOrDie(name);
116        Symbol symbol;
117        symbol.state = state;
118        bool result = mTable->setSymbolStateAllowMangled(resName, id, symbol, &mDiagnostics);
119        assert(result);
120        return *this;
121    }
122
123    std::unique_ptr<ResourceTable> build() {
124        return std::move(mTable);
125    }
126};
127
128inline std::unique_ptr<Reference> buildReference(const StringPiece16& ref,
129                                                 Maybe<ResourceId> id = {}) {
130    std::unique_ptr<Reference> reference = util::make_unique<Reference>(parseNameOrDie(ref));
131    reference->id = id;
132    return reference;
133}
134
135inline std::unique_ptr<BinaryPrimitive> buildPrimitive(uint8_t type, uint32_t data) {
136    android::Res_value value = {};
137    value.size = sizeof(value);
138    value.dataType = type;
139    value.data = data;
140    return util::make_unique<BinaryPrimitive>(value);
141}
142
143template <typename T>
144class ValueBuilder {
145private:
146    std::unique_ptr<Value> mValue;
147
148public:
149    template <typename... Args>
150    ValueBuilder(Args&&... args) : mValue(new T{ std::forward<Args>(args)... }) {
151    }
152
153    template <typename... Args>
154    ValueBuilder& setSource(Args&&... args) {
155        mValue->setSource(Source{ std::forward<Args>(args)... });
156        return *this;
157    }
158
159    ValueBuilder& setComment(const StringPiece16& str) {
160        mValue->setComment(str);
161        return *this;
162    }
163
164    std::unique_ptr<Value> build() {
165        return std::move(mValue);
166    }
167};
168
169class AttributeBuilder {
170private:
171    std::unique_ptr<Attribute> mAttr;
172
173public:
174    AttributeBuilder(bool weak = false) : mAttr(util::make_unique<Attribute>(weak)) {
175        mAttr->typeMask = android::ResTable_map::TYPE_ANY;
176    }
177
178    AttributeBuilder& setTypeMask(uint32_t typeMask) {
179        mAttr->typeMask = typeMask;
180        return *this;
181    }
182
183    AttributeBuilder& addItem(const StringPiece16& name, uint32_t value) {
184        mAttr->symbols.push_back(Attribute::Symbol{
185                Reference(ResourceName{ {}, ResourceType::kId, name.toString()}),
186                value});
187        return *this;
188    }
189
190    std::unique_ptr<Attribute> build() {
191        return std::move(mAttr);
192    }
193};
194
195class StyleBuilder {
196private:
197    std::unique_ptr<Style> mStyle = util::make_unique<Style>();
198
199public:
200    StyleBuilder& setParent(const StringPiece16& str) {
201        mStyle->parent = Reference(parseNameOrDie(str));
202        return *this;
203    }
204
205    StyleBuilder& addItem(const StringPiece16& str, std::unique_ptr<Item> value) {
206        mStyle->entries.push_back(Style::Entry{ Reference(parseNameOrDie(str)), std::move(value) });
207        return *this;
208    }
209
210    StyleBuilder& addItem(const StringPiece16& str, ResourceId id, std::unique_ptr<Item> value) {
211        addItem(str, std::move(value));
212        mStyle->entries.back().key.id = id;
213        return *this;
214    }
215
216    std::unique_ptr<Style> build() {
217        return std::move(mStyle);
218    }
219};
220
221class StyleableBuilder {
222private:
223    std::unique_ptr<Styleable> mStyleable = util::make_unique<Styleable>();
224
225public:
226    StyleableBuilder& addItem(const StringPiece16& str, Maybe<ResourceId> id = {}) {
227        mStyleable->entries.push_back(Reference(parseNameOrDie(str)));
228        mStyleable->entries.back().id = id;
229        return *this;
230    }
231
232    std::unique_ptr<Styleable> build() {
233        return std::move(mStyleable);
234    }
235};
236
237inline std::unique_ptr<xml::XmlResource> buildXmlDom(const StringPiece& str) {
238    std::stringstream in;
239    in << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" << str;
240    StdErrDiagnostics diag;
241    std::unique_ptr<xml::XmlResource> doc = xml::inflate(&in, &diag, Source("test.xml"));
242    assert(doc);
243    return doc;
244}
245
246inline std::unique_ptr<xml::XmlResource> buildXmlDomForPackageName(IAaptContext* context,
247                                                                   const StringPiece& str) {
248    std::unique_ptr<xml::XmlResource> doc = buildXmlDom(str);
249    doc->file.name.package = context->getCompilationPackage();
250    return doc;
251}
252
253} // namespace test
254} // namespace aapt
255
256#endif /* AAPT_TEST_BUILDERS_H */
257