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
CompileForAppend(const FileInfo & fileInfo)112 uint32_t IResourceCompiler::CompileForAppend(const FileInfo &fileInfo)
113 {
114 return CompileSingleFile(fileInfo);
115 }
116
GetResourceItems() const117 const map<pair<ResType, string>, vector<ResourceItem>> &IResourceCompiler::GetResourceItems() const
118 {
119 return nameInfos_;
120 }
121
SetModuleName(const string & moduleName)122 void IResourceCompiler::SetModuleName(const string &moduleName)
123 {
124 moduleName_ = moduleName;
125 }
126
ConvertToSolidXml(const map<string,vector<FileInfo>> & setsByDirectory)127 uint32_t IResourceCompiler::ConvertToSolidXml(const map<string, vector<FileInfo>> &setsByDirectory)
128 {
129 for (const auto &iter : setsByDirectory) {
130 vector<string> xmlPaths;
131 ListXmlFile(iter.second, xmlPaths);
132 if (xmlPaths.empty()) {
133 continue;
134 }
135
136 string xmlOutPath = iter.first;
137 if (!ResourceUtil::CreateDirs(xmlOutPath)) {
138 return RESTOOL_ERROR;
139 }
140
141 sort(xmlPaths.begin(), xmlPaths.end());
142 XmlConverter xmlConverter(xmlPaths, xmlOutPath);
143 if (!xmlConverter.GenerateSolidXml()) {
144 return RESTOOL_ERROR;
145 }
146
147 if (!xmlConverter.GenerateKey()) {
148 return RESTOOL_ERROR;
149 }
150 }
151 return RESTOOL_SUCCESS;
152 }
153
CompileSingleFile(const FileInfo & fileInfo)154 uint32_t IResourceCompiler::CompileSingleFile(const FileInfo &fileInfo)
155 {
156 return RESTOOL_SUCCESS;
157 }
158
PostCommit()159 uint32_t IResourceCompiler::PostCommit()
160 {
161 IdWorker &idWorker = IdWorker::GetInstance();
162 for (const auto &nameInfo : nameInfos_) {
163 int32_t id = idWorker.GenerateId(nameInfo.first.first, nameInfo.first.second);
164 if (id < 0) {
165 cerr << "Error: restype='" << ResourceUtil::ResTypeToString(nameInfo.first.first) << "' name='";
166 cerr << nameInfo.first.second << "' id not be defined." << endl;
167 return RESTOOL_ERROR;
168 }
169 resourceInfos_.emplace(id, nameInfo.second);
170 }
171 return RESTOOL_SUCCESS;
172 }
173
MergeResourceItem(const ResourceItem & resourceItem)174 bool IResourceCompiler::MergeResourceItem(const ResourceItem &resourceItem)
175 {
176 if (previewMode_) {
177 return SqliteDatabase::GetInstance().Insert(resourceItem);
178 }
179 string idName = ResourceUtil::GetIdName(resourceItem.GetName(), resourceItem.GetResType());
180 if (!IdWorker::GetInstance().IsValidName(idName)) {
181 cerr << "Error: invalid idName '" << idName << "'."<< NEW_LINE_PATH << resourceItem.GetFilePath() << endl;
182 return false;
183 }
184 auto item = nameInfos_.find(make_pair(resourceItem.GetResType(), idName));
185 if (item == nameInfos_.end()) {
186 nameInfos_[make_pair(resourceItem.GetResType(), idName)].push_back(resourceItem);
187 return true;
188 }
189
190 auto ret = find_if(item->second.begin(), item->second.end(), [resourceItem](auto &iter) {
191 return resourceItem.GetLimitKey() == iter.GetLimitKey();
192 });
193 if (ret != item->second.end()) {
194 cerr << "Error: resource '" << idName << "' first declared." << NEW_LINE_PATH << ret->GetFilePath() << endl;
195 cerr << "but declare again." << NEW_LINE_PATH << resourceItem.GetFilePath() << endl;
196 return false;
197 }
198
199 nameInfos_[make_pair(resourceItem.GetResType(), idName)].push_back(resourceItem);
200 return true;
201 }
202
ListXmlFile(const vector<FileInfo> & fileInfos,vector<string> & xmlPaths) const203 void IResourceCompiler::ListXmlFile(const vector<FileInfo> &fileInfos, vector<string> &xmlPaths) const
204 {
205 for (const auto &fileInfo : fileInfos) {
206 if (!IsXmlFile(fileInfo)) {
207 continue;
208 }
209
210 if (HasConvertedToSolidXml(fileInfo)) {
211 continue;
212 }
213 xmlPaths.push_back(fileInfo.filePath);
214 }
215 }
216
IsXmlFile(const FileInfo & fileInfo) const217 bool IResourceCompiler::IsXmlFile(const FileInfo &fileInfo) const
218 {
219 if (FileEntry::FilePath(fileInfo.filePath).GetExtension() != ".xml") {
220 return false;
221 }
222 return true;
223 }
224
HasConvertedToSolidXml(const FileInfo & fileInfo) const225 bool IResourceCompiler::HasConvertedToSolidXml(const FileInfo &fileInfo) const
226 {
227 string solidXmlPath = FileEntry::FilePath(output_).Append(RESOURCES_DIR).Append(fileInfo.limitKey)
228 .Append(fileInfo.fileCluster).Append(fileInfo.filename).ReplaceExtension(".sxml").GetPath();
229 if (ResourceUtil::FileExist(solidXmlPath)) {
230 return true;
231 }
232 return false;
233 }
234
NeedIfConvertToSolidXml() const235 bool IResourceCompiler::NeedIfConvertToSolidXml() const
236 {
237 return ResourceUtil::NeedConverToSolidXml(type_);
238 }
239
GetOutputFolder(const DirectoryInfo & directoryInfo) const240 string IResourceCompiler::GetOutputFolder(const DirectoryInfo &directoryInfo) const
241 {
242 string outputFolder = FileEntry::FilePath(output_).Append(RESOURCES_DIR)
243 .Append(directoryInfo.limitKey).Append(directoryInfo.fileCluster).GetPath();
244 return outputFolder;
245 }
246 }
247 }
248 }
249