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
41using std::string;
42
43const CSelectionCriterionRule::SMatchingRuleDescription CSelectionCriterionRule::_astMatchesWhen[CSelectionCriterionRule::ENbMatchesWhen] = {
44    { "Is", true },
45    { "IsNot", true },
46    { "Includes", false },
47    { "Excludes", false }
48};
49
50CSelectionCriterionRule::CSelectionCriterionRule() : _pSelectionCriterion(NULL), _eMatchesWhen(CSelectionCriterionRule::EIs), _iMatchValue(0)
51{
52}
53
54// Class kind
55string CSelectionCriterionRule::getKind() const
56{
57    return "SelectionCriterionRule";
58}
59
60// Content dumping
61void CSelectionCriterionRule::logValue(string& strValue, CErrorContext& errorContext) const
62{
63    (void)errorContext;
64
65    // Dump rule
66    dump(strValue);
67}
68
69// Parse
70bool 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
119void 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
134bool 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
154bool 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
198void 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
219bool 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