1 /*
2  * Copyright (c) 2011-2014, Intel Corporation
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without modification,
6  * are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice, this
9  * list of conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions and the following disclaimer in the documentation and/or
13  * other materials provided with the distribution.
14  *
15  * 3. Neither the name of the copyright holder nor the names of its contributors
16  * may be used to endorse or promote products derived from this software without
17  * specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
23  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 #include "SelectionCriterionRule.h"
31 #include "SelectionCriterion.h"
32 #include "XmlDomainSerializingContext.h"
33 #include "XmlDomainImportContext.h"
34 #include "SelectionCriteriaDefinition.h"
35 #include "SelectionCriterionTypeInterface.h"
36 #include "RuleParser.h"
37 #include <assert.h>
38 
39 #define base CRule
40 
41 using std::string;
42 
43 const CSelectionCriterionRule::SMatchingRuleDescription
44     CSelectionCriterionRule::_astMatchesWhen[CSelectionCriterionRule::ENbMatchesWhen] = {
45         {"Is", true}, {"IsNot", true}, {"Includes", false}, {"Excludes", false}};
46 
47 // Class kind
getKind() const48 string CSelectionCriterionRule::getKind() const
49 {
50     return "SelectionCriterionRule";
51 }
52 
53 // Content dumping
logValue(utility::ErrorContext &) const54 string CSelectionCriterionRule::logValue(utility::ErrorContext & /*cxt*/) const
55 {
56     // Dump rule
57     return dump();
58 }
59 
60 // Parse
parse(CRuleParser & ruleParser,string & strError)61 bool CSelectionCriterionRule::parse(CRuleParser &ruleParser, string &strError)
62 {
63     // Criterion
64     _pSelectionCriterion =
65         ruleParser.getSelectionCriteriaDefinition()->getSelectionCriterion(ruleParser.getType());
66 
67     // Check existence
68     if (!_pSelectionCriterion) {
69 
70         strError = "Couldn't find selection criterion " + ruleParser.getType();
71 
72         return false;
73     }
74 
75     // Verb
76     string strMatchesWhen;
77 
78     if (!ruleParser.next(strMatchesWhen, strError)) {
79 
80         return false;
81     }
82     // Value
83     string strValue;
84 
85     if (!ruleParser.next(strValue, strError)) {
86 
87         return false;
88     }
89 
90     // Matches when
91     if (!setMatchesWhen(strMatchesWhen, strError)) {
92 
93         strError = "Verb error: " + strError;
94 
95         return false;
96     }
97 
98     // Value
99     if (!_pSelectionCriterion->getCriterionType()->getNumericalValue(strValue, _iMatchValue)) {
100 
101         strError = "Value error: \"" + strValue + "\" is not part of criterion \"" +
102                    _pSelectionCriterion->getCriterionName() + "\"";
103 
104         return false;
105     }
106 
107     return true;
108 }
109 
110 // Dump
dump() const111 string CSelectionCriterionRule::dump() const
112 {
113     // Value
114     string value;
115     _pSelectionCriterion->getCriterionType()->getLiteralValue(_iMatchValue, value);
116 
117     // "<Name> <Verb> <Value>"
118     return string(_pSelectionCriterion->getName()) + " " +
119            _astMatchesWhen[_eMatchesWhen].pcMatchesWhen + " " + value;
120 }
121 
122 // Rule check
matches() const123 bool CSelectionCriterionRule::matches() const
124 {
125     assert(_pSelectionCriterion);
126 
127     switch (_eMatchesWhen) {
128     case EIs:
129         return _pSelectionCriterion->is(_iMatchValue);
130     case EIsNot:
131         return _pSelectionCriterion->isNot(_iMatchValue);
132     case EIncludes:
133         return _pSelectionCriterion->includes(_iMatchValue);
134     case EExcludes:
135         return _pSelectionCriterion->excludes(_iMatchValue);
136     default:
137         assert(0);
138         return false;
139     }
140 }
141 
142 // From IXmlSink
fromXml(const CXmlElement & xmlElement,CXmlSerializingContext & serializingContext)143 bool CSelectionCriterionRule::fromXml(const CXmlElement &xmlElement,
144                                       CXmlSerializingContext &serializingContext)
145 {
146     // Retrieve actual context
147     CXmlDomainImportContext &xmlDomainImportContext =
148         static_cast<CXmlDomainImportContext &>(serializingContext);
149 
150     // Get selection criterion
151     string strSelectionCriterion;
152     xmlElement.getAttribute("SelectionCriterion", strSelectionCriterion);
153 
154     _pSelectionCriterion =
155         xmlDomainImportContext.getSelectionCriteriaDefinition()->getSelectionCriterion(
156             strSelectionCriterion);
157 
158     // Check existence
159     if (!_pSelectionCriterion) {
160 
161         xmlDomainImportContext.setError("Couldn't find selection criterion " +
162                                         strSelectionCriterion + " in " + getKind() + " " +
163                                         xmlElement.getPath());
164 
165         return false;
166     }
167 
168     // Get MatchesWhen
169     string strMatchesWhen;
170     xmlElement.getAttribute("MatchesWhen", strMatchesWhen);
171     string strError;
172 
173     if (!setMatchesWhen(strMatchesWhen, strError)) {
174 
175         xmlDomainImportContext.setError("Wrong MatchesWhen attribute " + strMatchesWhen + " in " +
176                                         getKind() + " " + xmlElement.getPath() + ": " + strError);
177 
178         return false;
179     }
180 
181     // Get Value
182     string strValue;
183     xmlElement.getAttribute("Value", strValue);
184 
185     if (!_pSelectionCriterion->getCriterionType()->getNumericalValue(strValue, _iMatchValue)) {
186 
187         xmlDomainImportContext.setError("Wrong Value attribute value " + strValue + " in " +
188                                         getKind() + " " + xmlElement.getPath());
189 
190         return false;
191     }
192 
193     // Done
194     return true;
195 }
196 
197 // From IXmlSource
toXml(CXmlElement & xmlElement,CXmlSerializingContext &) const198 void CSelectionCriterionRule::toXml(CXmlElement &xmlElement, CXmlSerializingContext & /*ctx*/) const
199 {
200     assert(_pSelectionCriterion);
201 
202     // Set selection criterion
203     xmlElement.setAttribute("SelectionCriterion", _pSelectionCriterion->getName());
204 
205     // Set MatchesWhen
206     xmlElement.setAttribute("MatchesWhen", _astMatchesWhen[_eMatchesWhen].pcMatchesWhen);
207 
208     // Set Value
209     string strValue;
210 
211     _pSelectionCriterion->getCriterionType()->getLiteralValue(_iMatchValue, strValue);
212 
213     xmlElement.setAttribute("Value", strValue);
214 }
215 
216 // XML MatchesWhen attribute parsing
setMatchesWhen(const string & strMatchesWhen,string & strError)217 bool CSelectionCriterionRule::setMatchesWhen(const string &strMatchesWhen, string &strError)
218 {
219     for (size_t matchesWhen = 0; matchesWhen < ENbMatchesWhen; matchesWhen++) {
220 
221         const SMatchingRuleDescription *pstMatchingRuleDescription = &_astMatchesWhen[matchesWhen];
222 
223         if (strMatchesWhen == pstMatchingRuleDescription->pcMatchesWhen) {
224 
225             // Found it!
226 
227             // Get Type
228             const ISelectionCriterionTypeInterface *pSelectionCriterionType =
229                 _pSelectionCriterion->getCriterionType();
230 
231             // Check compatibility if relevant
232             if (!pSelectionCriterionType->isTypeInclusive() &&
233                 !pstMatchingRuleDescription->bExclusiveTypeCompatible) {
234 
235                 strError = "Value incompatible with exclusive kind of type";
236 
237                 return false;
238             }
239 
240             // Store
241             _eMatchesWhen = (MatchesWhen)matchesWhen;
242 
243             return true;
244         }
245     }
246 
247     strError = "Value not found";
248 
249     return false;
250 }
251