blob: 0ef67eaf3dc5fb764ea4bcb8ff9838cf245d64d8 [file] [log] [blame]
Adam Lesinskicc5609d2016-04-05 12:41:07 -07001/*
2 * Copyright (C) 2016 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#include "xml/XmlActionExecutor.h"
18
19namespace aapt {
20namespace xml {
21
22static bool wrapperOne(XmlNodeAction::ActionFunc& f, Element* el, SourcePathDiagnostics*) {
23 return f(el);
24}
25
26static bool wrapperTwo(XmlNodeAction::ActionFuncWithDiag& f, Element* el,
27 SourcePathDiagnostics* diag) {
28 return f(el, diag);
29}
30
31void XmlNodeAction::action(XmlNodeAction::ActionFunc f) {
32 mActions.emplace_back(std::bind(wrapperOne, std::move(f),
33 std::placeholders::_1,
34 std::placeholders::_2));
35}
36
37void XmlNodeAction::action(XmlNodeAction::ActionFuncWithDiag f) {
38 mActions.emplace_back(std::bind(wrapperTwo, std::move(f),
39 std::placeholders::_1,
40 std::placeholders::_2));
41}
42
43static void printElementToDiagMessage(const Element* el, DiagMessage* msg) {
44 *msg << "<";
45 if (!el->namespaceUri.empty()) {
46 *msg << el->namespaceUri << ":";
47 }
48 *msg << el->name << ">";
49}
50
51bool XmlNodeAction::execute(XmlActionExecutorPolicy policy, SourcePathDiagnostics* diag,
52 Element* el) const {
53 bool error = false;
54 for (const ActionFuncWithDiag& action : mActions) {
55 error |= !action(el, diag);
56 }
57
58 for (Element* childEl : el->getChildElements()) {
59 if (childEl->namespaceUri.empty()) {
60 std::map<std::u16string, XmlNodeAction>::const_iterator iter =
61 mMap.find(childEl->name);
62 if (iter != mMap.end()) {
63 error |= !iter->second.execute(policy, diag, childEl);
64 continue;
65 }
66 }
67
68 if (policy == XmlActionExecutorPolicy::Whitelist) {
69 DiagMessage errorMsg(childEl->lineNumber);
70 errorMsg << "unknown element ";
71 printElementToDiagMessage(childEl, &errorMsg);
72 errorMsg << " found";
73 diag->error(errorMsg);
74 error = true;
75 }
76 }
77 return !error;
78}
79
80bool XmlActionExecutor::execute(XmlActionExecutorPolicy policy, IDiagnostics* diag,
81 XmlResource* doc) const {
82 SourcePathDiagnostics sourceDiag(doc->file.source, diag);
83
84 Element* el = findRootElement(doc);
85 if (!el) {
86 if (policy == XmlActionExecutorPolicy::Whitelist) {
87 sourceDiag.error(DiagMessage() << "no root XML tag found");
88 return false;
89 }
90 return true;
91 }
92
93 if (el->namespaceUri.empty()) {
94 std::map<std::u16string, XmlNodeAction>::const_iterator iter = mMap.find(el->name);
95 if (iter != mMap.end()) {
96 return iter->second.execute(policy, &sourceDiag, el);
97 }
98 }
99
100 if (policy == XmlActionExecutorPolicy::Whitelist) {
101 DiagMessage errorMsg(el->lineNumber);
102 errorMsg << "unknown element ";
103 printElementToDiagMessage(el, &errorMsg);
104 errorMsg << " found";
105 sourceDiag.error(errorMsg);
106 return false;
107 }
108 return true;
109}
110
111} // namespace xml
112} // namespace aapt