| 1 | /////////////////////////////////////////////////////////////////////////////// |
| 2 | // Copyright (c) 2000-2014 Ericsson Telecom AB |
| 3 | // All rights reserved. This program and the accompanying materials |
| 4 | // are made available under the terms of the Eclipse Public License v1.0 |
| 5 | // which accompanies this distribution, and is available at |
| 6 | // http://www.eclipse.org/legal/epl-v10.html |
| 7 | /////////////////////////////////////////////////////////////////////////////// |
| 8 | #ifndef _Common_Constraint_HH |
| 9 | #define _Common_Constraint_HH |
| 10 | |
| 11 | #include "Setting.hh" |
| 12 | |
| 13 | namespace Asn { |
| 14 | class Block; |
| 15 | } |
| 16 | |
| 17 | namespace Common { |
| 18 | |
| 19 | /** |
| 20 | * \ingroup Type |
| 21 | * |
| 22 | * \defgroup Constraint Constraint specifications |
| 23 | * |
| 24 | * These classes provide a unified interface for constraints. |
| 25 | * |
| 26 | * @{ |
| 27 | */ |
| 28 | |
| 29 | class Constraint; |
| 30 | class Constraints; |
| 31 | |
| 32 | // not defined here |
| 33 | class Type; |
| 34 | class Value; |
| 35 | class SubtypeConstraint; |
| 36 | class Identifier; |
| 37 | |
| 38 | using Asn::Block; |
| 39 | |
| 40 | /** |
| 41 | * Class to represent Constraint. |
| 42 | */ |
| 43 | class Constraint : public Node, public Location { |
| 44 | public: |
| 45 | enum constrtype_t { |
| 46 | CT_ELEMENTSETSPEC, /** ElementSetSpecsConstraint */ |
| 47 | CT_IGNORE, /**< Constraint : used if erroneous or not yet supported */ |
| 48 | CT_TABLE, /**< TableConstraint */ |
| 49 | CT_SINGLEVALUE, /**< SingleValueConstraint */ |
| 50 | CT_CONTAINEDSUBTYPE, /**< ContainedSubtypeConstraint */ |
| 51 | CT_VALUERANGE, /**< ValueRangeConstraint */ |
| 52 | CT_SIZE, /**< SizeConstraint */ |
| 53 | CT_PERMITTEDALPHABET, /**< PermittedAlphabetConstraint */ |
| 54 | CT_PATTERN, /**< PatternConstraint */ |
| 55 | CT_SETOPERATION, /**< SetOperationConstraint */ |
| 56 | CT_FULLSET, /**< FullSetConstraint */ |
| 57 | CT_SINGLEINNERTYPE, /**< SingleInnerTypeConstraint */ |
| 58 | CT_NAMED, /**< NamedConstraint */ |
| 59 | CT_UNPARSEDMULTIPLEINNERTYPE, /**< UnparsedMultipleInnerTypeConstraint */ |
| 60 | CT_MULTIPLEINNERTYPE /**< MultipleInnerTypeConstraint */ |
| 61 | }; |
| 62 | protected: |
| 63 | constrtype_t constrtype; |
| 64 | Type* my_type; /**< the type to which this constraint belongs to */ |
| 65 | Scope* my_scope; /**< scope or NULL, if NULL then get scope from my_type */ |
| 66 | Constraint* my_parent; /**< the parent constraint node in AST or NULL */ |
| 67 | Constraints* my_cons; /**< the Constraints object or NULL, it is set if this |
| 68 | is the root node of a constraint tree */ |
| 69 | bool checked; /**< set to true by chk() */ |
| 70 | SubtypeConstraint* subtype; /**< NULL or set by chk() if constraint is valid, this is the root part */ |
| 71 | bool extendable; /**< set by chk() */ |
| 72 | SubtypeConstraint* extension; /**< NULL if there is no extension or not valid, set by chk() */ |
| 73 | |
| 74 | Constraint(const Constraint& p); |
| 75 | /// Assignment disabled |
| 76 | Constraint& operator=(const Constraint& p); |
| 77 | public: |
| 78 | Constraint(constrtype_t p_constrtype); |
| 79 | virtual ~Constraint(); |
| 80 | virtual Constraint* clone() const = 0; |
| 81 | constrtype_t get_constrtype() const { return constrtype; } |
| 82 | void set_my_type(Type *p_my_type) { my_type = p_my_type; } |
| 83 | void set_my_parent(Constraint* p_my_parent) { my_parent = p_my_parent; } |
| 84 | Constraint* get_my_parent() const { return my_parent; } |
| 85 | void set_my_scope(Scope* p_my_scope) { my_scope = p_my_scope; } |
| 86 | Scope* get_my_scope(); |
| 87 | void set_my_cons(Constraints* p_my_cons); |
| 88 | Constraints* get_my_cons(); |
| 89 | virtual void chk() = 0; |
| 90 | /** return the subtype constraint */ |
| 91 | SubtypeConstraint* get_subtype() const { return subtype; } |
| 92 | bool is_extendable() const { return extendable; } |
| 93 | SubtypeConstraint* get_extension() const { return extension; } |
| 94 | /** returns the name of this constraint which can be used in error messages */ |
| 95 | virtual const char* get_name() const = 0; |
| 96 | /** if this constraint is inside a FROM() constraint then we are in |
| 97 | a char context */ |
| 98 | bool in_char_context() const; |
| 99 | /** returns true if this constraint is inside a single or multiple inner type constraint */ |
| 100 | bool in_inner_constraint() const; |
| 101 | /** returns if this kind of constraint is ignored, when ignored the |
| 102 | full set is used as it's subtype value |
| 103 | TODO: set operations which have operands that are ignored constraints should |
| 104 | somehow drop or simplify their constraint, example: (inner subtype) EXCEPT (inner subtype) |
| 105 | */ |
| 106 | virtual bool is_ignored() const { return false; } |
| 107 | }; |
| 108 | |
| 109 | /** |
| 110 | * Class to represent constraints. |
| 111 | */ |
| 112 | class Constraints : public Node { |
| 113 | private: |
| 114 | vector<Constraint> cons; |
| 115 | Type *my_type; |
| 116 | SubtypeConstraint* subtype; /**< NULL or set by chk() if constraint is valid, this is the root part */ |
| 117 | bool extendable; /**< set by chk() */ |
| 118 | SubtypeConstraint* extension; /**< NULL if there is no extension or not valid, set by chk() */ |
| 119 | |
| 120 | Constraints(const Constraints& p); |
| 121 | /// Assignment disabled |
| 122 | Constraints& operator=(const Constraints& p); |
| 123 | public: |
| 124 | Constraints() : Node(), cons(), my_type(0), subtype(0), extendable(false), extension(0) {} |
| 125 | virtual ~Constraints(); |
| 126 | virtual Constraints *clone() const; |
| 127 | void add_con(Constraint *p_con); |
| 128 | size_t get_nof_cons() const {return cons.size();} |
| 129 | Constraint* get_con_byIndex(size_t p_i) const { return cons[p_i]; } |
| 130 | Constraint* get_tableconstraint() const; |
| 131 | void set_my_type(Type *p_my_type); |
| 132 | Type* get_my_type() const { return my_type; } |
| 133 | void chk(SubtypeConstraint* parent_subtype); |
| 134 | void chk_table(); |
| 135 | /* return the subtype constraint */ |
| 136 | SubtypeConstraint* get_subtype() const { return subtype; } |
| 137 | bool is_extendable() const { return extendable; } |
| 138 | SubtypeConstraint* get_extension() const { return extension; } |
| 139 | }; |
| 140 | |
| 141 | /** @} end of Constraint group */ |
| 142 | |
| 143 | |
| 144 | // ================================= |
| 145 | // ===== ElementSetSpecsConstraint |
| 146 | // ================================= |
| 147 | |
| 148 | /* This AST element is used only if "..." is present, otherwise it's not |
| 149 | created, therefore the extendable bool is always true in this constraint */ |
| 150 | class ElementSetSpecsConstraint : public Constraint |
| 151 | { |
| 152 | Constraint* root_constr; |
| 153 | Constraint* ext_constr; /* NULL if no extension addition was present */ |
| 154 | ElementSetSpecsConstraint(const ElementSetSpecsConstraint& p); |
| 155 | /// Assignment disabled |
| 156 | ElementSetSpecsConstraint& operator=(const ElementSetSpecsConstraint& p); |
| 157 | public: |
| 158 | ElementSetSpecsConstraint(Constraint* p_root_constr, Constraint* p_ext_constr); |
| 159 | virtual ~ElementSetSpecsConstraint(); |
| 160 | ElementSetSpecsConstraint* clone() const { return new ElementSetSpecsConstraint(*this); } |
| 161 | void chk(); |
| 162 | const char* get_name() const { return "ElementSetSpecs constraint"; } |
| 163 | void set_fullname(const string& p_fullname); |
| 164 | }; |
| 165 | |
| 166 | // ================================= |
| 167 | // ===== IgnoredConstraint |
| 168 | // ================================= |
| 169 | |
| 170 | class IgnoredConstraint : public Constraint |
| 171 | { |
| 172 | const char* my_name; |
| 173 | IgnoredConstraint(const IgnoredConstraint& p); |
| 174 | /// Assignment disabled |
| 175 | IgnoredConstraint& operator=(const IgnoredConstraint& p); |
| 176 | public: |
| 177 | IgnoredConstraint(const char* p_name); |
| 178 | IgnoredConstraint* clone() const { return new IgnoredConstraint(*this); } |
| 179 | void chk(); |
| 180 | const char* get_name() const { return my_name; } |
| 181 | bool is_ignored() const { return true; } |
| 182 | }; |
| 183 | |
| 184 | |
| 185 | // ================================= |
| 186 | // ===== SingleValueConstraint |
| 187 | // ================================= |
| 188 | |
| 189 | class SingleValueConstraint : public Constraint |
| 190 | { |
| 191 | Value* value; |
| 192 | SingleValueConstraint(const SingleValueConstraint& p); |
| 193 | /// Assignment disabled |
| 194 | SingleValueConstraint& operator=(const SingleValueConstraint& p); |
| 195 | public: |
| 196 | SingleValueConstraint(Value* p_value); |
| 197 | virtual ~SingleValueConstraint(); |
| 198 | SingleValueConstraint* clone() const { return new SingleValueConstraint(*this); } |
| 199 | void chk(); |
| 200 | const char* get_name() const { return "single value constraint"; } |
| 201 | void set_fullname(const string& p_fullname); |
| 202 | }; |
| 203 | |
| 204 | // ================================= |
| 205 | // ===== ContainedSubtypeConstraint |
| 206 | // ================================= |
| 207 | |
| 208 | class ContainedSubtypeConstraint : public Constraint |
| 209 | { |
| 210 | Type* type; |
| 211 | bool has_includes; /**< INCLUDES keyword was used, then this cannot be a TypeConstraint, |
| 212 | otherwise it can be both TypeConstraint and ContainedSubtypeConstraint */ |
| 213 | ContainedSubtypeConstraint(const ContainedSubtypeConstraint& p); |
| 214 | /// Assignment disabled |
| 215 | ContainedSubtypeConstraint& operator=(const ContainedSubtypeConstraint& p); |
| 216 | public: |
| 217 | ContainedSubtypeConstraint(Type* p_type, bool p_has_includes); |
| 218 | virtual ~ContainedSubtypeConstraint(); |
| 219 | ContainedSubtypeConstraint* clone() const { return new ContainedSubtypeConstraint(*this); } |
| 220 | void chk(); |
| 221 | const char* get_name() const { return "contained subtype constraint"; } |
| 222 | void set_fullname(const string& p_fullname); |
| 223 | }; |
| 224 | |
| 225 | // ================================= |
| 226 | // ===== RangeEndpoint |
| 227 | // ================================= |
| 228 | |
| 229 | class ValueRangeConstraint; |
| 230 | |
| 231 | class RangeEndpoint : public Node, public Location |
| 232 | { |
| 233 | public: |
| 234 | enum endpoint_t { |
| 235 | MIN, /**< minimum value */ |
| 236 | VALUE, /**< value */ |
| 237 | MAX /**< maximum value */ |
| 238 | }; |
| 239 | private: |
| 240 | endpoint_t type; /**< type of endpoint */ |
| 241 | Value* value; /**< a value or NULL if type!=VALUE */ |
| 242 | bool inclusive; /**< true if the endpoint is part of the range */ |
| 243 | RangeEndpoint(const RangeEndpoint& p); |
| 244 | RangeEndpoint& operator=(const RangeEndpoint& p); // = disabled |
| 245 | public: |
| 246 | RangeEndpoint(endpoint_t p_type); |
| 247 | RangeEndpoint(Value* p_value); |
| 248 | void set_exclusive() { inclusive = false; } |
| 249 | bool get_exclusive() const { return !inclusive; } |
| 250 | endpoint_t get_type() const { return type; } |
| 251 | Value* get_value() const { return value; } |
| 252 | ~RangeEndpoint(); |
| 253 | RangeEndpoint* clone() const { return new RangeEndpoint(*this); } |
| 254 | void chk(Type* my_type, ValueRangeConstraint* constraint); |
| 255 | void set_fullname(const string& p_fullname); |
| 256 | }; |
| 257 | |
| 258 | // ================================= |
| 259 | // ===== ValueRangeConstraint |
| 260 | // ================================= |
| 261 | |
| 262 | class ValueRangeConstraint : public Constraint |
| 263 | { |
| 264 | RangeEndpoint* lower_endpoint; |
| 265 | RangeEndpoint* upper_endpoint; |
| 266 | ValueRangeConstraint(const ValueRangeConstraint& p); |
| 267 | /// Assignment disabled |
| 268 | ValueRangeConstraint& operator=(const ValueRangeConstraint& p); |
| 269 | public: |
| 270 | ValueRangeConstraint(RangeEndpoint* p_lower, RangeEndpoint* p_upper); |
| 271 | virtual ~ValueRangeConstraint() { delete lower_endpoint; delete upper_endpoint; } |
| 272 | ValueRangeConstraint* clone() const { return new ValueRangeConstraint(*this); } |
| 273 | void chk(); |
| 274 | const char* get_name() const { return "value range constraint"; } |
| 275 | void set_fullname(const string& p_fullname); |
| 276 | }; |
| 277 | |
| 278 | // ================================= |
| 279 | // ===== SizeConstraint |
| 280 | // ================================= |
| 281 | |
| 282 | class SizeConstraint : public Constraint |
| 283 | { |
| 284 | Constraint* constraint; |
| 285 | SizeConstraint(const SizeConstraint& p); |
| 286 | /// Assignment disabled |
| 287 | SizeConstraint& operator=(const SizeConstraint& p); |
| 288 | public: |
| 289 | SizeConstraint(Constraint* p); |
| 290 | virtual ~SizeConstraint() { delete constraint; } |
| 291 | SizeConstraint* clone() const { return new SizeConstraint(*this); } |
| 292 | void chk(); |
| 293 | const char* get_name() const { return "size constraint"; } |
| 294 | void set_fullname(const string& p_fullname); |
| 295 | }; |
| 296 | |
| 297 | // ================================= |
| 298 | // ===== PermittedAlphabetConstraint |
| 299 | // ================================= |
| 300 | |
| 301 | class PermittedAlphabetConstraint : public Constraint |
| 302 | { |
| 303 | Constraint* constraint; |
| 304 | PermittedAlphabetConstraint(const PermittedAlphabetConstraint& p); |
| 305 | /// Assignment disabled |
| 306 | PermittedAlphabetConstraint& operator=(const PermittedAlphabetConstraint& p); |
| 307 | public: |
| 308 | PermittedAlphabetConstraint(Constraint* p); |
| 309 | virtual ~PermittedAlphabetConstraint() { delete constraint; } |
| 310 | PermittedAlphabetConstraint* clone() const { return new PermittedAlphabetConstraint(*this); } |
| 311 | void chk(); |
| 312 | const char* get_name() const { return "permitted alphabet constraint"; } |
| 313 | void set_fullname(const string& p_fullname); |
| 314 | }; |
| 315 | |
| 316 | // ================================= |
| 317 | // ===== SetOperationConstraint |
| 318 | // ================================= |
| 319 | |
| 320 | class SetOperationConstraint : public Constraint |
| 321 | { |
| 322 | public: |
| 323 | enum operationtype_t { |
| 324 | UNION, |
| 325 | INTERSECTION, |
| 326 | EXCEPT |
| 327 | }; |
| 328 | private: |
| 329 | operationtype_t operationtype; |
| 330 | Constraint* operand_a; |
| 331 | Constraint* operand_b; |
| 332 | SetOperationConstraint(const SetOperationConstraint& p); |
| 333 | /// Assignment disabled |
| 334 | SetOperationConstraint& operator=(const SetOperationConstraint& p); |
| 335 | public: |
| 336 | SetOperationConstraint(Constraint* p_a, operationtype_t p_optype, Constraint* p_b); |
| 337 | virtual ~SetOperationConstraint() { delete operand_a; delete operand_b; } |
| 338 | void set_first_operand(Constraint* p_a); |
| 339 | SetOperationConstraint* clone() const { return new SetOperationConstraint(*this); } |
| 340 | const char* get_operationtype_str() const; |
| 341 | void chk(); |
| 342 | const char* get_name() const { return get_operationtype_str(); } |
| 343 | void set_fullname(const string& p_fullname); |
| 344 | }; |
| 345 | |
| 346 | // ================================= |
| 347 | // ===== FullSetConstraint |
| 348 | // ================================= |
| 349 | |
| 350 | class FullSetConstraint : public Constraint |
| 351 | { |
| 352 | FullSetConstraint(const FullSetConstraint& p): Constraint(p) {} |
| 353 | /// Assignment disabled |
| 354 | FullSetConstraint& operator=(const FullSetConstraint& p); |
| 355 | public: |
| 356 | FullSetConstraint(): Constraint(CT_FULLSET) {} |
| 357 | FullSetConstraint* clone() const { return new FullSetConstraint(*this); } |
| 358 | void chk(); |
| 359 | const char* get_name() const { return "ALL"; } |
| 360 | }; |
| 361 | |
| 362 | // ================================= |
| 363 | // ===== PatternConstraint |
| 364 | // ================================= |
| 365 | |
| 366 | class PatternConstraint : public Constraint |
| 367 | { |
| 368 | Value* value; |
| 369 | PatternConstraint(const PatternConstraint& p); |
| 370 | /// Assignment disabled |
| 371 | PatternConstraint& operator=(const PatternConstraint& p); |
| 372 | public: |
| 373 | PatternConstraint(Value* p_value); |
| 374 | virtual ~PatternConstraint(); |
| 375 | PatternConstraint* clone() const { return new PatternConstraint(*this); } |
| 376 | void chk(); |
| 377 | const char* get_name() const { return "pattern constraint"; } |
| 378 | void set_fullname(const string& p_fullname); |
| 379 | bool is_ignored() const { return true; } |
| 380 | }; |
| 381 | |
| 382 | // ================================= |
| 383 | // ===== SingleInnerTypeConstraint |
| 384 | // ================================= |
| 385 | |
| 386 | class SingleInnerTypeConstraint : public Constraint |
| 387 | { |
| 388 | Constraint* constraint; |
| 389 | SingleInnerTypeConstraint(const SingleInnerTypeConstraint& p); |
| 390 | /// Assignment disabled |
| 391 | SingleInnerTypeConstraint& operator=(const SingleInnerTypeConstraint& p); |
| 392 | public: |
| 393 | SingleInnerTypeConstraint(Constraint* p); |
| 394 | virtual ~SingleInnerTypeConstraint() { delete constraint; } |
| 395 | SingleInnerTypeConstraint* clone() const { return new SingleInnerTypeConstraint(*this); } |
| 396 | void chk(); |
| 397 | void set_fullname(const string& p_fullname); |
| 398 | const char* get_name() const { return "inner type constraint"; } |
| 399 | bool is_ignored() const { return true; } |
| 400 | }; |
| 401 | |
| 402 | // ================================= |
| 403 | // ===== NamedConstraint |
| 404 | // ================================= |
| 405 | |
| 406 | class NamedConstraint : public Constraint |
| 407 | { |
| 408 | public: |
| 409 | enum presence_constraint_t { |
| 410 | PC_NONE, // presence constraint was not specified |
| 411 | PC_PRESENT, |
| 412 | PC_ABSENT, |
| 413 | PC_OPTIONAL |
| 414 | }; |
| 415 | private: |
| 416 | Identifier* id; |
| 417 | Constraint* value_constraint; // NULL if it was not specified |
| 418 | presence_constraint_t presence_constraint; |
| 419 | NamedConstraint(const NamedConstraint& p); |
| 420 | /// Assignment disabled |
| 421 | NamedConstraint& operator=(const NamedConstraint& p); |
| 422 | public: |
| 423 | NamedConstraint(Identifier* p_id, Constraint* p_value_constraint, presence_constraint_t p_presence_constraint); |
| 424 | ~NamedConstraint(); |
| 425 | const Identifier& get_id() const { return *id; } |
| 426 | Constraint* get_value_constraint() const { return value_constraint; } |
| 427 | presence_constraint_t get_presence_constraint() const { return presence_constraint; } |
| 428 | const char* get_presence_constraint_name() const; |
| 429 | NamedConstraint* clone() const { return new NamedConstraint(*this); } |
| 430 | void chk(); |
| 431 | void set_fullname(const string& p_fullname); |
| 432 | const char* get_name() const { return "named constraint"; } |
| 433 | bool is_ignored() const { return true; } |
| 434 | }; |
| 435 | |
| 436 | // ================================= |
| 437 | // ===== MultipleInnerTypeConstraint |
| 438 | // ================================= |
| 439 | |
| 440 | class MultipleInnerTypeConstraint : public Constraint |
| 441 | { |
| 442 | bool partial; // Full/Partial Specification |
| 443 | vector<NamedConstraint> named_con_vec; |
| 444 | map<Identifier,NamedConstraint> named_con_map; // values owned by named_con_vec, filled by chk() |
| 445 | MultipleInnerTypeConstraint(const MultipleInnerTypeConstraint& p); |
| 446 | /// Assignment disabled |
| 447 | MultipleInnerTypeConstraint& operator=(const MultipleInnerTypeConstraint& p); |
| 448 | public: |
| 449 | MultipleInnerTypeConstraint(): Constraint(CT_MULTIPLEINNERTYPE) {} |
| 450 | virtual ~MultipleInnerTypeConstraint(); |
| 451 | MultipleInnerTypeConstraint* clone() const { return new MultipleInnerTypeConstraint(*this); } |
| 452 | |
| 453 | void set_partial(bool b) { partial = b; } |
| 454 | bool get_partial() const { return partial; } |
| 455 | void addNamedConstraint(NamedConstraint* named_con); |
| 456 | |
| 457 | void chk(); |
| 458 | void set_fullname(const string& p_fullname); |
| 459 | const char* get_name() const { return "inner type constraint"; } |
| 460 | bool is_ignored() const { return true; } |
| 461 | }; |
| 462 | |
| 463 | // ================================= |
| 464 | // ===== UnparsedMultipleInnerTypeConstraint |
| 465 | // ================================= |
| 466 | |
| 467 | class UnparsedMultipleInnerTypeConstraint : public Constraint |
| 468 | { |
| 469 | Block* block; |
| 470 | MultipleInnerTypeConstraint* constraint; |
| 471 | UnparsedMultipleInnerTypeConstraint(const UnparsedMultipleInnerTypeConstraint& p); |
| 472 | /// Assignment disabled |
| 473 | UnparsedMultipleInnerTypeConstraint& operator=(const UnparsedMultipleInnerTypeConstraint& p); |
| 474 | public: |
| 475 | UnparsedMultipleInnerTypeConstraint(Block* p_block); |
| 476 | virtual ~UnparsedMultipleInnerTypeConstraint(); |
| 477 | UnparsedMultipleInnerTypeConstraint* clone() const { return new UnparsedMultipleInnerTypeConstraint(*this); } |
| 478 | void chk(); |
| 479 | void set_fullname(const string& p_fullname); |
| 480 | const char* get_name() const { return "inner type constraint"; } |
| 481 | bool is_ignored() const { return true; } |
| 482 | }; |
| 483 | |
| 484 | } // namespace Common |
| 485 | |
| 486 | #endif // _Common_Constraint_HH |