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 CSelectionCriterionRule::_astMatchesWhen[CSelectionCriterionRule::ENbMatchesWhen] = {
44     { "Is", true },
45     { "IsNot", true },
46     { "Includes", false },
47     { "Excludes", false }
48 };
49 
CSelectionCriterionRule()50 CSelectionCriterionRule::CSelectionCriterionRule() : _pSelectionCriterion(NULL), _eMatchesWhen(CSelectionCriterionRule::EIs), _iMatchValue(0)
51 {
52 }
53 
54 // Class kind
getKind() const55 string CSelectionCriterionRule::getKind() const
56 {
57     return "SelectionCriterionRule";
58 }
59 
60 // Content dumping
logValue(string & strValue,CErrorContext & errorContext) const61 void CSelectionCriterionRule::logValue(string& strValue, CErrorContext& errorContext) const
62 {
63     (void)errorContext;
64 
65     // Dump rule
66     dump(strValue);
67 }
68 
69 // Parse
parse(CRuleParser & ruleParser,string & strError)70 bool CSelectionCriterionRule::parse(CRuleParser& ruleParser, string& strError)
71 {
72     // Criterion
73     _pSelectionCriterion = ruleParser.getSelectionCriteriaDefinition()->getSelectionCriterion(ruleParser.getType());
74 
75     // Check existence
76     if (!_pSelectionCriterion) {
77 
78         strError = "Couldn't find selection criterion " + ruleParser.getType();
79 
80         return false;
81     }
82 
83     // Verb
84     string strMatchesWhen;
85 
86     if (!ruleParser.next(strMatchesWhen, strError)) {
87 
88         return false;
89     }
90     // Value
91     string strValue;
92 
93     if (!ruleParser.next(strValue, strError)) {
94 
95         return false;
96     }
97 
98     // Matches when
99     if (!setMatchesWhen(strMatchesWhen, strError)) {
100 
101         strError = "Verb error: " + strError;
102 
103         return false;
104     }
105 
106     // Value
107     if (!_pSelectionCriterion->getCriterionType()->getNumericalValue(strValue, _iMatchValue)) {
108 
109         strError = "Value error: \"" + strValue + "\" is not part of criterion \"" +
110                    _pSelectionCriterion->getCriterionName() + "\"";
111 
112         return false;
113     }
114 
115     return true;
116 }
117 
118 // Dump
dump(string & strResult) const119 void CSelectionCriterionRule::dump(string& strResult) const
120 {
121     // Criterion
122     strResult += _pSelectionCriterion->getName();
123     strResult += " ";
124     // Verb
125     strResult += _astMatchesWhen[_eMatchesWhen].pcMatchesWhen;
126     strResult += " ";
127     // Value
128     string strValue;
129     _pSelectionCriterion->getCriterionType()->getLiteralValue(_iMatchValue, strValue);
130     strResult += strValue;
131 }
132 
133 // Rule check
matches() const134 bool CSelectionCriterionRule::matches() const
135 {
136     assert(_pSelectionCriterion);
137 
138     switch(_eMatchesWhen) {
139     case EIs:
140         return _pSelectionCriterion->is(_iMatchValue);
141     case EIsNot:
142         return _pSelectionCriterion->isNot(_iMatchValue);
143     case EIncludes:
144         return _pSelectionCriterion->includes(_iMatchValue);
145     case EExcludes:
146         return _pSelectionCriterion->excludes(_iMatchValue);
147     default:
148         assert(0);
149         return false;
150     }
151 }
152 
153 // From IXmlSink
fromXml(const CXmlElement & xmlElement,CXmlSerializingContext & serializingContext)154 bool CSelectionCriterionRule::fromXml(const CXmlElement& xmlElement, CXmlSerializingContext& serializingContext)
155 {
156     // Retrieve actual context
157     CXmlDomainImportContext& xmlDomainImportContext = static_cast<CXmlDomainImportContext&>(serializingContext);
158 
159     // Get selection criterion
160     string strSelectionCriterion = xmlElement.getAttributeString("SelectionCriterion");
161 
162     _pSelectionCriterion = xmlDomainImportContext.getSelectionCriteriaDefinition()->getSelectionCriterion(strSelectionCriterion);
163 
164     // Check existence
165     if (!_pSelectionCriterion) {
166 
167         xmlDomainImportContext.setError("Couldn't find selection criterion " + strSelectionCriterion + " in " + getKind() + " " + xmlElement.getPath());
168 
169         return false;
170     }
171 
172     // Get MatchesWhen
173     string strMatchesWhen = xmlElement.getAttributeString("MatchesWhen");
174     string strError;
175 
176     if (!setMatchesWhen(strMatchesWhen, strError)) {
177 
178         xmlDomainImportContext.setError("Wrong MatchesWhen attribute " + strMatchesWhen + " in " + getKind() + " " + xmlElement.getPath() + ": " + strError);
179 
180         return false;
181     }
182 
183     // Get Value
184     string strValue = xmlElement.getAttributeString("Value");
185 
186     if (!_pSelectionCriterion->getCriterionType()->getNumericalValue(strValue, _iMatchValue)) {
187 
188         xmlDomainImportContext.setError("Wrong Value attribute value " + strValue + " in " + getKind() + " " + xmlElement.getPath());
189 
190         return false;
191     }
192 
193     // Done
194     return true;
195 }
196 
197 // From IXmlSource
toXml(CXmlElement & xmlElement,CXmlSerializingContext & serializingContext) const198 void CSelectionCriterionRule::toXml(CXmlElement& xmlElement, CXmlSerializingContext& serializingContext) const
199 {
200     (void)serializingContext;
201 
202     assert(_pSelectionCriterion);
203 
204     // Set selection criterion
205     xmlElement.setAttributeString("SelectionCriterion", _pSelectionCriterion->getName());
206 
207     // Set MatchesWhen
208     xmlElement.setAttributeString("MatchesWhen", _astMatchesWhen[_eMatchesWhen].pcMatchesWhen);
209 
210     // Set Value
211     string strValue;
212 
213      _pSelectionCriterion->getCriterionType()->getLiteralValue(_iMatchValue, strValue);
214 
215     xmlElement.setAttributeString("Value", strValue);
216 }
217 
218 // XML MatchesWhen attribute parsing
setMatchesWhen(const string & strMatchesWhen,string & strError)219 bool CSelectionCriterionRule::setMatchesWhen(const string& strMatchesWhen, string& strError)
220 {
221     uint32_t uiMatchesWhen;
222 
223     for (uiMatchesWhen = 0; uiMatchesWhen < ENbMatchesWhen; uiMatchesWhen++) {
224 
225         const SMatchingRuleDescription* pstMatchingRuleDescription = &_astMatchesWhen[uiMatchesWhen];
226 
227         if (strMatchesWhen == pstMatchingRuleDescription->pcMatchesWhen) {
228 
229             // Found it!
230 
231             // Get Type
232             const ISelectionCriterionTypeInterface* pSelectionCriterionType = _pSelectionCriterion->getCriterionType();
233 
234             // Check compatibility if relevant
235             if (!pSelectionCriterionType->isTypeInclusive() && !pstMatchingRuleDescription->bExclusiveTypeCompatible) {
236 
237                 strError = "Value incompatible with exclusive kind of type";
238 
239                 return false;
240             }
241 
242             // Store
243             _eMatchesWhen = (MatchesWhen)uiMatchesWhen;
244 
245             return true;
246         }
247     }
248 
249     strError = "Value not found";
250 
251     return false;
252 }
253