1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "i_resource_compiler.h"
17 #include <algorithm>
18 #include <iostream>
19 #include "file_entry.h"
20 #include "id_worker.h"
21 #include "resource_util.h"
22 #include "restool_errors.h"
23 #include "sqlite_database.h"
24 #include "xml_converter.h"
25
26 namespace OHOS {
27 namespace Global {
28 namespace Restool {
29 using namespace std;
IResourceCompiler(ResType type,const string & output)30 IResourceCompiler::IResourceCompiler(ResType type, const string &output)
31 :type_(type), output_(output)
32 {
33 }
34
~IResourceCompiler()35 IResourceCompiler::~IResourceCompiler()
36 {
37 nameInfos_.clear();
38 resourceInfos_.clear();
39 }
40
Compile(const vector<DirectoryInfo> & directoryInfos)41 uint32_t IResourceCompiler::Compile(const vector<DirectoryInfo> &directoryInfos)
42 {
43 vector<FileInfo> fileInfos;
44 map<string, vector<FileInfo>> setsByDirectory;
45 for (const auto &directoryInfo : directoryInfos) {
46 string outputFolder = GetOutputFolder(directoryInfo);
47 FileEntry f(directoryInfo.dirPath);
48 if (!f.Init()) {
49 return RESTOOL_ERROR;
50 }
51 for (const auto &it : f.GetChilds()) {
52 if (ResourceUtil::IsIgnoreFile(it->GetFilePath().GetFilename(), it->IsFile())) {
53 continue;
54 }
55
56 if (!it->IsFile()) {
57 cout << "Error: '" << it->GetFilePath().GetPath() << "' not regular." << endl;
58 return RESTOOL_ERROR;
59 }
60
61 FileInfo fileInfo = { directoryInfo, it->GetFilePath().GetPath(), it->GetFilePath().GetFilename() };
62 fileInfos.push_back(fileInfo);
63 setsByDirectory[outputFolder].push_back(fileInfo);
64 }
65 }
66
67 sort(fileInfos.begin(), fileInfos.end(), [](const auto &a, const auto &b) {
68 return a.filePath < b.filePath;
69 });
70 for (const auto &fileInfo : fileInfos) {
71 if (CompileSingleFile(fileInfo) != RESTOOL_SUCCESS) {
72 return RESTOOL_ERROR;
73 }
74 }
75
76 if (previewMode_) {
77 return RESTOOL_SUCCESS;
78 }
79 if (NeedIfConvertToSolidXml() && ConvertToSolidXml(setsByDirectory) != RESTOOL_SUCCESS) {
80 return RESTOOL_ERROR;
81 }
82 return PostCommit();
83 }
84
GetResult() const85 const map<int32_t, vector<ResourceItem>> &IResourceCompiler::GetResult() const
86 {
87 return resourceInfos_;
88 }
89
Compile(const FileInfo & fileInfo)90 uint32_t IResourceCompiler::Compile(const FileInfo &fileInfo)
91 {
92 if (CompileSingleFile(fileInfo) != RESTOOL_SUCCESS) {
93 return RESTOOL_ERROR;
94 }
95
96 if (previewMode_) {
97 return RESTOOL_SUCCESS;
98 }
99 map<string, vector<FileInfo>> setsByDirectory;
100 if (NeedIfConvertToSolidXml()) {
101 string outputFolder = FileEntry::FilePath(output_).Append(RESOURCES_DIR)
102 .Append(fileInfo.limitKey).Append(fileInfo.fileCluster).GetPath();
103 setsByDirectory[outputFolder].push_back(fileInfo);
104 }
105
106 if (ConvertToSolidXml(setsByDirectory) != RESTOOL_SUCCESS) {
107 return RESTOOL_ERROR;
108 }
109 return PostCommit();
110 }
111
SetModuleName(const string & moduleName)112 void IResourceCompiler::SetModuleName(const string &moduleName)
113 {
114 moduleName_ = moduleName;
115 }
116
ConvertToSolidXml(const map<string,vector<FileInfo>> & setsByDirectory)117 uint32_t IResourceCompiler::ConvertToSolidXml(const map<string, vector<FileInfo>> &setsByDirectory)
118 {
119 for (const auto &iter : setsByDirectory) {
120 vector<string> xmlPaths;
121 ListXmlFile(iter.second, xmlPaths);
122 if (xmlPaths.empty()) {
123 continue;
124 }
125
126 string xmlOutPath = iter.first;
127 if (!ResourceUtil::CreateDirs(xmlOutPath)) {
128 return RESTOOL_ERROR;
129 }
130
131 sort(xmlPaths.begin(), xmlPaths.end());
132 XmlConverter xmlConverter(xmlPaths, xmlOutPath);
133 if (!xmlConverter.GenerateSolidXml()) {
134 return RESTOOL_ERROR;
135 }
136
137 if (!xmlConverter.GenerateKey()) {
138 return RESTOOL_ERROR;
139 }
140 }
141 return RESTOOL_SUCCESS;
142 }
143
CompileSingleFile(const FileInfo & fileInfo)144 uint32_t IResourceCompiler::CompileSingleFile(const FileInfo &fileInfo)
145 {
146 return RESTOOL_SUCCESS;
147 }
148
PostCommit()149 uint32_t IResourceCompiler::PostCommit()
150 {
151 IdWorker &idWorker = IdWorker::GetInstance();
152 for (const auto &nameInfo : nameInfos_) {
153 int32_t id = idWorker.GenerateId(nameInfo.first.first, nameInfo.first.second);
154 if (id < 0) {
155 cerr << "Error: restype='" << ResourceUtil::ResTypeToString(nameInfo.first.first) << "' name='";
156 cerr << nameInfo.first.second << "' id not be defined." << endl;
157 return RESTOOL_ERROR;
158 }
159 resourceInfos_.emplace(id, nameInfo.second);
160 }
161 return RESTOOL_SUCCESS;
162 }
163
MergeResourceItem(const ResourceItem & resourceItem)164 bool IResourceCompiler::MergeResourceItem(const ResourceItem &resourceItem)
165 {
166 if (previewMode_) {
167 return SqliteDatabase::GetInstance().Insert(resourceItem);
168 }
169 string idName = ResourceUtil::GetIdName(resourceItem.GetName(), resourceItem.GetResType());
170 if (!IdWorker::GetInstance().IsValidName(idName)) {
171 cerr << "Error: in " << resourceItem.GetFilePath() << endl;
172 return false;
173 }
174 auto item = nameInfos_.find(make_pair(resourceItem.GetResType(), idName));
175 if (item == nameInfos_.end()) {
176 nameInfos_[make_pair(resourceItem.GetResType(), idName)].push_back(resourceItem);
177 return true;
178 }
179
180 auto ret = find_if(item->second.begin(), item->second.end(), [resourceItem](auto &iter) {
181 return resourceItem.GetLimitKey() == iter.GetLimitKey();
182 });
183 if (ret != item->second.end()) {
184 cerr << "Error: resource '" << idName << "' first declared in " << ret->GetFilePath();
185 cerr << ", but declare again in " << resourceItem.GetFilePath() << endl;
186 return false;
187 }
188
189 nameInfos_[make_pair(resourceItem.GetResType(), idName)].push_back(resourceItem);
190 return true;
191 }
192
ListXmlFile(const vector<FileInfo> & fileInfos,vector<string> & xmlPaths) const193 void IResourceCompiler::ListXmlFile(const vector<FileInfo> &fileInfos, vector<string> &xmlPaths) const
194 {
195 for (const auto &fileInfo : fileInfos) {
196 if (!IsXmlFile(fileInfo)) {
197 continue;
198 }
199
200 if (HasConvertedToSolidXml(fileInfo)) {
201 continue;
202 }
203 xmlPaths.push_back(fileInfo.filePath);
204 }
205 }
206
IsXmlFile(const FileInfo & fileInfo) const207 bool IResourceCompiler::IsXmlFile(const FileInfo &fileInfo) const
208 {
209 if (FileEntry::FilePath(fileInfo.filePath).GetExtension() != ".xml") {
210 return false;
211 }
212 return true;
213 }
214
HasConvertedToSolidXml(const FileInfo & fileInfo) const215 bool IResourceCompiler::HasConvertedToSolidXml(const FileInfo &fileInfo) const
216 {
217 string solidXmlPath = FileEntry::FilePath(output_).Append(RESOURCES_DIR).Append(fileInfo.limitKey)
218 .Append(fileInfo.fileCluster).Append(fileInfo.filename).ReplaceExtension(".sxml").GetPath();
219 if (ResourceUtil::FileExist(solidXmlPath)) {
220 return true;
221 }
222 return false;
223 }
224
NeedIfConvertToSolidXml() const225 bool IResourceCompiler::NeedIfConvertToSolidXml() const
226 {
227 return ResourceUtil::NeedConverToSolidXml(type_);
228 }
229
GetOutputFolder(const DirectoryInfo & directoryInfo) const230 string IResourceCompiler::GetOutputFolder(const DirectoryInfo &directoryInfo) const
231 {
232 string outputFolder = FileEntry::FilePath(output_).Append(RESOURCES_DIR)
233 .Append(directoryInfo.limitKey).Append(directoryInfo.fileCluster).GetPath();
234 return outputFolder;
235 }
236 }
237 }
238 }
239