1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2001-2019 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials
5 // are made available under the terms of the Eclipse Public License v2.0
6 // which accompanies this distribution, and is available at
7 // http://www.eclipse.org/legal/epl-v20.html
8 // SPDX-License-Identifier: EPL-2.0
9 /****************************************************************************/
10 /// @file    GNEAttributeCarrier.h
11 /// @author  Jakob Erdmann
12 /// @date    Mar 2011
13 /// @version $Id$
14 ///
15 // Abstract Base class for gui objects which carry attributes
16 /****************************************************************************/
17 #ifndef GNEAttributeCarrier_h
18 #define GNEAttributeCarrier_h
19 
20 
21 // ===========================================================================
22 // included modules
23 // ===========================================================================
24 #include <config.h>
25 
26 #include <utils/common/MsgHandler.h>
27 #include <utils/common/ToString.h>
28 #include <utils/common/UtilExceptions.h>
29 #include <utils/gui/images/GUIIcons.h>
30 #include <utils/gui/settings/GUIVisualizationSettings.h>
31 #include <utils/xml/SUMOSAXAttributes.h>
32 #include <utils/xml/SUMOXMLDefinitions.h>
33 
34 #include "GNEReferenceCounter.h"
35 
36 
37 // ===========================================================================
38 // class declarations
39 // ===========================================================================
40 class GNENet;
41 class GNEUndoList;
42 class GNELane;
43 class GNEEdge;
44 
45 // ===========================================================================
46 // class definitions
47 // ===========================================================================
48 /**
49  * @class GNEAttributeCarrier
50  *
51  * Abstract Base class for gui objects which carry attributes
52  * inherits from GNEReferenceCounter for convenience
53  */
54 class GNEAttributeCarrier : public GNEReferenceCounter {
55 
56     /// @brief declare friend class
57     friend class GNEChange_Attribute;
58 
59 public:
60 
61     // @brief declare class TagProperties
62     class TagProperties;
63 
64     /// @brief struct with the tag Properties
65     enum AttrProperty {
66         ATTRPROPERTY_INT =            1 << 0,   // Attribute is an integer (Including Zero)
67         ATTRPROPERTY_FLOAT =          1 << 1,   // Attribute is a float
68         ATTRPROPERTY_BOOL =           1 << 2,   // Attribute is boolean (0/1, true/false)
69         ATTRPROPERTY_STRING =         1 << 3,   // Attribute is a string
70         ATTRPROPERTY_POSITION =       1 << 4,   // Attribute is a position defined by doubles (x,y or x,y,z)
71         ATTRPROPERTY_COLOR =          1 << 5,   // Attribute is a color defined by a specifically word (Red, green) or by a special format (XXX,YYY,ZZZ)
72         ATTRPROPERTY_VCLASS =         1 << 6,   // Attribute is a VClass (passenger, bus, motorcicle...)
73         ATTRPROPERTY_POSITIVE =       1 << 7,   // Attribute is positive (Including Zero)
74         ATTRPROPERTY_NOTZERO =        1 << 8,   // Attribute cannot be 0 (only for numerical attributes)
75         ATTRPROPERTY_UNIQUE =         1 << 9,   // Attribute is unique (cannot be edited in a selection of similar elements (ID, Position...)
76         ATTRPROPERTY_FILENAME =       1 << 10,  // Attribute is a filename (string that cannot contains certain characters)
77         ATTRPROPERTY_NONEDITABLE =    1 << 11,  // Attribute is non editable (index of a lane)
78         ATTRPROPERTY_DISCRETE =       1 << 12,  // Attribute is discrete (only certain values are allowed)
79         ATTRPROPERTY_PROBABILITY =    1 << 13,  // Attribute is probability (only allowed values between 0 and 1, including both)
80         ATTRPROPERTY_TIME =           1 << 14,  // Attribute is a Time (float positive)
81         ATTRPROPERTY_ANGLE =          1 << 15,  // Attribute is an angle (only takes values between 0 and 360, including both, another value will be automatically reduced
82         ATTRPROPERTY_LIST =           1 << 16,  // Attribute is a list of other elements separated by spaces
83         ATTRPROPERTY_SECUENCIAL =     1 << 17,  // Attribute is a special sequence of elements (for example: secuencial lanes in Multi Lane E2 detectors)
84         ATTRPROPERTY_OPTIONAL =       1 << 18,  // Attribute is optional
85         ATTRPROPERTY_DEFAULTVALUE =   1 << 19,  // Attribute owns a default value
86         ATTRPROPERTY_COMBINABLE =     1 << 20,  // Attribute is combinable with other Attribute
87         ATTRPROPERTY_SYNONYM =        1 << 21,  // Attribute will be written with a different name in der XML
88         ATTRPROPERTY_RANGE =          1 << 22,  // Attribute only accept a range of elements
89         ATTRPROPERTY_EXTENDED =       1 << 23,  // Attribute is extended (used in certain demand elements)
90         ATTRPROPERTY_UPDATEGEOMETRY = 1 << 24,  // Attribute requiere update geometry at the end of function setAttribute(...)
91     };
92 
93     /// @brief struct with the attribute Properties
94     class AttributeProperties {
95 
96     public:
97         /// @brief default constructor
98         AttributeProperties();
99 
100         /// @brief parameter constructor
101         AttributeProperties(const SumoXMLAttr attribute, const int attributeProperty, const std::string& definition, std::string defaultValue = "");
102 
103         /// @brief destructor
104         ~AttributeProperties();
105 
106         /// @brief check Attribute integrity (For example, throw an exception if tag has a Float default value, but given default value cannot be parse to float)
107         void checkAttributeIntegrity();
108 
109         /// @brief set discrete values
110         void setDiscreteValues(const std::vector<std::string>& discreteValues);
111 
112         /// @brief set synonim
113         void setSynonym(const SumoXMLAttr synonym);
114 
115         /// @brief set range
116         void setRange(const double minimum, const double maximum);
117 
118         /// @brief set position listed
119         void setPositionListed(const int positionListed);
120 
121         /// @brief set tag property parent
122         void setTagPropertyParent(TagProperties* tagPropertyParent);
123 
124         /// @brief get XML Attribute
125         SumoXMLAttr getAttr() const;
126 
127         /// @brief get XML Attribute
128         const std::string& getAttrStr() const;
129 
130         /// @brief get reference to tagProperty parent
131         const TagProperties& getTagPropertyParent() const;
132 
133         /// @brief get position in list (used in frames for listing attributes with certain sort)
134         int getPositionListed() const;
135 
136         /// @brief get default value
137         const std::string& getDefinition() const;
138 
139         /// @brief get default value
140         const std::string& getDefaultValue() const;
141 
142         /// @brief return a description of attribute
143         std::string getDescription() const;
144 
145         /// @brief get discrete values
146         const std::vector<std::string>& getDiscreteValues() const;
147 
148         /// @brief get tag synonym
149         SumoXMLAttr getAttrSynonym() const;
150 
151         /// @brief get minimum range
152         double getMinimumRange() const;
153 
154         /// @brief get maximum range
155         double getMaximumRange() const;
156 
157         /// @brief return true if attribute owns a default value
158         bool hasDefaultValue() const;
159 
160         /// @brief return true if Attr correspond to an element that will be written in XML with another name
161         bool hasAttrSynonym() const;
162 
163         /// @brief return true if Attr correspond to an element that only accept a range of values
164         bool hasAttrRange() const;
165 
166         /// @brief return true if atribute is an integer
167         bool isInt() const;
168 
169         /// @brief return true if atribute is a float
170         bool isFloat() const;
171 
172         /// @brief return true if atribute is boolean
173         bool isBool() const;
174 
175         /// @brief return true if atribute is a string
176         bool isString() const;
177 
178         /// @brief return true if atribute is a position
179         bool isposition() const;
180 
181         /// @brief return true if atribute is a probability
182         bool isProbability() const;
183 
184         /// @brief return true if atribute is numerical (int or float)
185         bool isNumerical() const;
186 
187         /// @brief return true if atribute is time
188         bool isTime() const;
189 
190         /// @brief return true if atribute is positive
191         bool isPositive() const;
192 
193         /// @brief return true if atribute cannot be zero
194         bool cannotBeZero() const;
195 
196         /// @brief return true if atribute is a color
197         bool isColor() const;
198 
199         /// @brief return true if atribute is a filename
200         bool isFilename() const;
201 
202         /// @brief return true if atribute is a VehicleClass
203         bool isVClass() const;
204 
205         /// @brief return true if atribute is a VehicleClass
206         bool isSVCPermission() const;
207 
208         /// @brief return true if atribute is a list
209         bool isList() const;
210 
211         /// @brief return true if atribute is sequential
212         bool isSecuential() const;
213 
214         /// @brief return true if atribute is unique
215         bool isUnique() const;
216 
217         /// @brief return true if atribute is optional
218         bool isOptional() const;
219 
220         /// @brief return true if atribute is discrete
221         bool isDiscrete() const;
222 
223         /// @brief return true if atribute is combinable with other Attribute
224         bool isCombinable() const;
225 
226         /// @brief return true if atribute isn't editable
227         bool isNonEditable() const;
228 
229         /// @brief return true if atribute is extended
230         bool isExtended() const;
231 
232         /// @brief return true if atribute requieres a update geometry in setAttribute(...)
233         bool requiereUpdateGeometry() const;
234 
235     private:
236         /// @brief XML Attribute
237         SumoXMLAttr myAttribute;
238 
239         /// @brief pointer to tagProperty parent
240         TagProperties* myTagPropertyParent;
241 
242         /// @brief string with the Attribute in text format (to avoid unnecesaries toStrings(...) calls)
243         std::string myAttrStr;
244 
245         /// @brief Property of attribute
246         int myAttributeProperty;
247 
248         /// @brief listed position
249         int myPositionListed;
250 
251         /// @brief text with a definition of attribute
252         std::string myDefinition;
253 
254         /// @brief default value (by default empty)
255         std::string myDefaultValue;
256 
257         /// @brief discrete values that can take this Attribute (by default empty)
258         std::vector<std::string> myDiscreteValues;
259 
260         /// @brief Attribute written in XML (If is SUMO_ATTR_NOTHING), original Attribute will be written)
261         SumoXMLAttr myAttrSynonym;
262 
263         /// @brief minimun Range
264         double myMinimumRange;
265 
266         /// @brief maxium Range
267         double myMaximumRange;
268     };
269 
270 
271     enum TagType {
272         TAGTYPE_NETELEMENT =    1 << 0,   // Edges, Junctions, Lanes...
273         TAGTYPE_ADDITIONAL =    1 << 1,   // Bus Stops, Charging Stations, Detectors...
274         TAGTYPE_SHAPE =         1 << 2,   // POIs, Polygons
275         TAGTYPE_DEMANDELEMENT = 1 << 3,   // Routes, Vehicles, Trips...
276         TAGTYPE_TAZ =           1 << 4,   // Traffic Assignment Zones
277         TAGTYPE_STOPPINGPLACE = 1 << 5,   // StoppingPlaces (BusStops, ChargingStations...)
278         TAGTYPE_DETECTOR =      1 << 6,   // Detectors (E1, E2...)
279         TAGTYPE_VEHICLE =       1 << 7,   // Vehicles (Flows, trips...)
280         TAGTYPE_ROUTEELEMENT =  1 << 8,   // VTypes, Vehicles, Flows...
281         TAGTYPE_STOP =          1 << 8,   // Stops
282     };
283 
284     enum TAGProperty {
285         TAGPROPERTY_DRAWABLE =            1 << 0,   // Element can be drawed in view
286         TAGPROPERTY_BLOCKMOVEMENT =       1 << 1,   // Element can block their movement
287         TAGPROPERTY_BLOCKSHAPE =          1 << 2,   // Element can block their shape
288         TAGPROPERTY_CLOSESHAPE =          1 << 3,   // Element can close their shape
289         TAGPROPERTY_GEOPOSITION =         1 << 4,   // Element's position can be defined using a GEO position
290         TAGPROPERTY_GEOSHAPE =            1 << 5,   // Element's shape acn be defined using a GEO Shape
291         TAGPROPERTY_DIALOG =              1 << 6,   // Element can be edited using a dialog (GNECalibratorDialog, GNERerouterDialog...)
292         TAGPROPERTY_PARENT =              1 << 7,   // Element will be writed in XML as child of another element (E3Entry -> E3Detector...)
293         TAGPROPERTY_MINIMUMCHILDS =       1 << 8,   // Element will be only writed in XML if has a minimum number of childs
294         TAGPROPERTY_REPARENT =            1 << 9,   // Element can be reparent
295         TAGPROPERTY_SYNONYM =             1 << 10,  // Element will be written with a different name in der XML
296         TAGPROPERTY_AUTOMATICSORTING =    1 << 11,  // Element sort automatic their Childs (used by Additionals)
297         TAGPROPERTY_SELECTABLE =          1 << 12,  // Element is selectable
298         TAGPROPERTY_MASKSTARTENDPOS =     1 << 13,  // Element mask attributes StartPos and EndPos as "lenght" (Only used in the appropiate GNEFrame)
299         TAGPROPERTY_MASKXYZPOSITION =     1 << 14,  // Element mask attributes X, Y and Z as "Position"
300         TAGPROPERTY_WRITECHILDSSEPARATE = 1 << 15,  // Element writes their childs in a separated filename
301         TAGPROPERTY_NOGENERICPARAMETERS = 1 << 16,  // Element doesn't accept Generic Parameters (by default all tags supports generic parameters)
302         TAGPROPERTY_DISJOINTATTRIBUTES =  1 << 17,  // Element owns attributes that cannot be defined together
303     };
304 
305     /// @brief struct with the attribute Properties
306     class TagProperties {
307     public:
308         /// @brief default constructor
309         TagProperties();
310 
311         /// @brief parameter constructor
312         TagProperties(SumoXMLTag tag, int tagType, int tagProperty, GUIIcon icon, SumoXMLTag parentTag = SUMO_TAG_NOTHING, SumoXMLTag tagSynonym = SUMO_TAG_NOTHING);
313 
314         /// @brief destructor
315         ~TagProperties();
316 
317         /// @brief get Tag vinculated with this attribute Property
318         SumoXMLTag getTag() const;
319 
320         /// @brief get Tag vinculated with this attribute Property in String Format (used to avoid multiple calls to toString(...)
321         const std::string& getTagStr() const;
322 
323         /// @brief check Tag integrity (this include all their attributes)
324         void checkTagIntegrity() const;
325 
326         /// @brief add attribute (duplicated attributed aren't allowed)
327         void addAttribute(const AttributeProperties& attributeProperty);
328 
329         /// @brief add deprecated Attribute
330         void addDeprecatedAttribute(SumoXMLAttr attr);
331 
332         /// @brief get attribute (throw error if doesn't exist)
333         const AttributeProperties& getAttributeProperties(SumoXMLAttr attr) const;
334 
335         /// @brief get begin of attribute values (used for iterate)
336         std::map<SumoXMLAttr, AttributeProperties>::const_iterator begin() const;
337 
338         /// @brief get end of attribute values (used for iterate)
339         std::map<SumoXMLAttr, AttributeProperties>::const_iterator end() const;
340 
341         /// @brief get number of attributes
342         int getNumberOfAttributes() const;
343 
344         /// @brief return the default value of the attribute of an element
345         const std::string& getDefaultValue(SumoXMLAttr attr) const;
346 
347         /// @brief get GUI icon associated to this Tag
348         GUIIcon getGUIIcon() const;
349 
350         /// @brief if Tag owns a parent, return parent tag
351         SumoXMLTag getParentTag() const;
352 
353         /// @brief get tag synonym
354         SumoXMLTag getTagSynonym() const;
355 
356         /// @brief set disjoint attributes
357         void setDisjointAttributes(const std::vector<SumoXMLAttr>& attrs);
358 
359         /// @brief check if given attribute is a disjoint attribute
360         bool isDisjointAttributes(SumoXMLAttr attr) const;
361 
362         /// @brief check if current TagProperties owns the attribute attr
363         bool hasAttribute(SumoXMLAttr attr) const;
364 
365         /// @brief return true if tag correspond to a netElement
366         bool isNetElement() const;
367 
368         /// @brief return true if tag correspond to an additional
369         bool isAdditional() const;
370 
371         /// @brief return true if tag correspond to a shape
372         bool isShape() const;
373 
374         /// @brief return true if tag correspond to a TAZ
375         bool isTAZ() const;
376 
377         /// @brief return true if tag correspond to a demand element
378         bool isDemandElement() const;
379 
380         /// @brief return true if tag correspond to a detector (Only used to group all stoppingPlaces in the output XML)
381         bool isStoppingPlace() const;
382 
383         /// @brief return true if tag correspond to a shape (Only used to group all detectors in the XML)
384         bool isDetector() const;
385 
386         /// @brief return true if tag correspond to a vehicle element
387         bool isVehicle() const;
388 
389         /// @brief return true if tag correspond to a stop element
390         bool isStop() const;
391 
392         /// @brief return true if tag correspond to a drawable element
393         bool isDrawable() const;
394 
395         /// @brief return true if tag correspond to a selectable element
396         bool isSelectable() const;
397 
398         /// @brief return true if tag correspond to an element that can block their movement
399         bool canBlockMovement() const;
400 
401         /// @brief return true if tag correspond to an element that can block their shape
402         bool canBlockShape() const;
403 
404         /// @brief return true if tag correspond to an element that can close their shape
405         bool canCloseShape() const;
406 
407         /// @brief return true if tag correspond to an element that can use a geo position
408         bool hasGEOPosition() const;
409 
410         /// @brief return true if tag correspond to an element that can use a geo shape
411         bool hasGEOShape() const;
412 
413         /// @brief return true if tag correspond to an element that can had another element as parent
414         bool hasParent() const;
415 
416         /// @brief return true if tag correspond to an element that will be written in XML with another tag
417         bool hasTagSynonym() const;
418 
419         /// @brief return true if tag correspond to an element that can be edited using a dialog
420         bool hasDialog() const;
421 
422         /// @brief return true if tag correspond to an element that only have a limited number of childs
423         bool hasMinimumNumberOfChilds() const;
424 
425         /// @brief return true if Tag correspond to an element that supports generic parameters
426         bool hasGenericParameters() const;
427 
428         /// @brief return true if Tag correspond to an element that has disjoint attributes
429         bool hasDisjointAttributes() const;
430 
431         /// @brief return true if tag correspond to an element that can be reparent
432         bool canBeReparent() const;
433 
434         /// @brief return true if tag correspond to an element that can sort their childs automatic
435         bool canAutomaticSortChilds() const;
436 
437         /// @brief return true if tag correspond to an element that can sort their childs automatic
438         bool canWriteChildsSeparate() const;
439 
440         /// @brief return true if tag correspond to an element that can mask the attributes "start" and "end" position as attribute "lenght"
441         bool canMaskStartEndPos() const;
442 
443         /// @brief return true if tag correspond to an element that can mask the attributes "X", "Y" and "Z" position as attribute "Position"
444         bool canMaskXYZPositions() const;
445 
446         /// @brief return true if attribute of this tag is deprecated
447         bool isAttributeDeprecated(SumoXMLAttr attr) const;
448 
449     private:
450         /// @brief Sumo XML Tag vinculated wit this tag Property
451         SumoXMLTag myTag;
452 
453         /// @brief Sumo XML Tag vinculated wit this tag Property in String format
454         std::string myTagStr;
455 
456         /// @brief Attribute Type
457         int myTagType;
458 
459         /// @brief Attribute properties
460         int myTagProperty;
461 
462         /// @brief map with the attribute values vinculated with this Tag
463         std::map<SumoXMLAttr, AttributeProperties> myAttributeProperties;
464 
465         /// @brief icon associated to this Tag
466         GUIIcon myIcon;
467 
468         /// @brief parent tag
469         SumoXMLTag myParentTag;
470 
471         /// @brief Tag written in XML (If is SUMO_TAG_NOTHING), original Tag name will be written)
472         SumoXMLTag myTagSynonym;
473 
474         /// @brief List with the deprecated Attributes
475         std::vector<SumoXMLAttr> myDeprecatedAttributes;
476 
477         /// @brief List of disjoint attributes
478         std::vector<SumoXMLAttr> myDisjointAttrs;
479 
480         /// @brief list of valid combinations of disjoint attributes
481         std::vector<std::pair<SumoXMLAttr, SumoXMLAttr> > myDisjointAttrsCombinations;
482     };
483 
484     /**@brief Constructor
485      * @param[in] tag SUMO Tag assigned to this type of object
486      * @param[in] icon GUIIcon associated to the type of object
487      */
488     GNEAttributeCarrier(const SumoXMLTag tag);
489 
490     /// @brief Destructor
491     virtual ~GNEAttributeCarrier();
492 
493     /// @name This functions has to be implemented in all GNEAttributeCarriers
494     /// @{
495     /// @brief select attribute carrier using GUIGlobalSelection
496     virtual void selectAttributeCarrier(bool changeFlag = true) = 0;
497 
498     /// @brief unselect attribute carrier using GUIGlobalSelection
499     virtual void unselectAttributeCarrier(bool changeFlag = true) = 0;
500 
501     /// @brief check if attribute carrier is selected
502     virtual bool isAttributeCarrierSelected() const = 0;
503 
504     /// @brief check if attribute carrier must be drawn using selecting color.
505     virtual bool drawUsingSelectColor() const = 0;
506 
507     /* @brief method for getting the Attribute of an XML key
508      * @param[in] key The attribute key
509      * @return string with the value associated to key
510      */
511     virtual std::string getAttribute(SumoXMLAttr key) const = 0;
512 
513     /* @brief method for setting the attribute and letting the object perform additional changes
514      * @param[in] key The attribute key
515      * @param[in] value The new value
516      * @param[in] undoList The undoList on which to register changes
517      */
518     virtual void setAttribute(SumoXMLAttr key, const std::string& value, GNEUndoList* undoList) = 0;
519 
520     /* @brief method for check if new value for certain attribute is valid
521      * @param[in] key The attribute key
522      * @param[in] value The new value
523      */
524     virtual bool isValid(SumoXMLAttr key, const std::string& value) = 0;
525 
526     /* @brief method for check if certain attribute is set (used by ACs with disjoint attributes)
527      * @param[in] key The attribute key
528      * @return true if it's set, false in other case
529      */
530     virtual bool isDisjointAttributeSet(const SumoXMLAttr attr) const;
531 
532     /* @brief method for set certain attribute is set (used by ACs with disjoint attributes)
533      * @param[in] attr The attribute key
534      * @param[in] undoList The undoList on which to register changes
535      */
536     virtual void setDisjointAttribute(const SumoXMLAttr attr, GNEUndoList* undoList);
537 
538     /// @brief get PopPup ID (Used in AC Hierarchy)
539     virtual std::string getPopUpID() const = 0;
540 
541     /// @brief get Hierarchy Name (Used in AC Hierarchy)
542     virtual std::string getHierarchyName() const = 0;
543     /// @}
544 
545     /// @name Certain attributes and ACs (for example, connections) can be either loaded or guessed. The following static variables are used to remark it.
546     /// @{
547     /// @brief feature is still unchanged after being loaded (implies approval)
548     static const std::string FEATURE_LOADED;
549 
550     /// @brief feature has been reguessed (may still be unchanged be we can't tell (yet)
551     static const std::string FEATURE_GUESSED;
552 
553     /// @brief feature has been manually modified (implies approval)
554     static const std::string FEATURE_MODIFIED;
555 
556     /// @brief feature has been approved but not changed (i.e. after being reguessed)
557     static const std::string FEATURE_APPROVED;
558     /// @}
559 
560     /// @brief invalid double position
561     static const double INVALID_POSITION;
562 
563     /// @brief method for getting the attribute in the context of object selection
564     virtual std::string getAttributeForSelection(SumoXMLAttr key) const;
565 
566     /// @brief get tag assigned to this object in string format
567     const std::string& getTagStr() const;
568 
569     /// @brief get Tag Property assigned to this object
570     const TagProperties& getTagProperty() const;
571 
572     /// @brief get FXIcon associated to this AC
573     FXIcon* getIcon() const;
574 
575     /// @brief function to support debugging
576     const std::string getID() const;
577 
578     /// @brief get Tag Properties
579     static const TagProperties& getTagProperties(SumoXMLTag tag);
580 
581     /// @brief get tags of all editable element types
582     static std::vector<SumoXMLTag> allowedTags(bool onlyDrawables);
583 
584     /// @brief get tags of all editable element types using TagProperty Type (TAGTYPE_NETELEMENT, TAGTYPE_ADDITIONAL, etc.)
585     static std::vector<SumoXMLTag> allowedTagsByCategory(int tagPropertyCategory, bool onlyDrawables);
586 
587     /// @brief return the number of attributes of the tag with the most highter number of attributes
588     static int getHigherNumberOfAttributes();
589 
590     /// @name This functions related with generic parameters has to be implemented in all GNEAttributeCarriers
591     /// @{
592 
593     /// @brief return generic parameters in string format
594     virtual std::string getGenericParametersStr() const = 0;
595 
596     /// @brief return generic parameters as vector of pairs format
597     virtual std::vector<std::pair<std::string, std::string> > getGenericParameters() const = 0;
598 
599     /// @brief set generic parameters in string format
600     virtual void setGenericParametersStr(const std::string& value) = 0;
601 
602     /// @}
603 
604     /// @brief check if given string can be parsed to a map/list of generic parameters
605     static bool isGenericParametersValid(const std::string& value);
606 
607     /// @brief true if a value of type T can be parsed from string
608     template<typename T>
canParse(const std::string & string)609     static bool canParse(const std::string& string) {
610         try {
611             parse<T>(string);
612         } catch (NumberFormatException&) {
613             return false;
614         } catch (EmptyData&) {
615             return false;
616         } catch (BoolFormatException&) {
617             return false;
618         }
619         return true;
620     }
621 
622     /// @brief parses a value of type T from string (used for basic types: int, double, bool, etc.)
623     template<typename T>
624     static T parse(const std::string& string);
625 
626     /// @brief true if a value of type T can be parsed from string
627     template<typename T>
canParse(GNENet * net,const std::string & value,bool report)628     static bool canParse(GNENet* net, const std::string& value, bool report) {
629         try {
630             parse<T>(net, value);
631         } catch (FormatException& exception) {
632             if (report) {
633                 WRITE_WARNING(exception.what())
634             }
635             return false;
636         }
637         return true;
638     }
639 
640     /// @brief parses a complex value of type T from string (use for list of edges, list of lanes, etc.)
641     template<typename T>
642     static T parse(GNENet* net, const std::string& value);
643 
644     /// @brief parses a list of specific Attribute Carriers into a string of IDs
645     template<typename T>
646     static std::string parseIDs(const std::vector<T>& ACs);
647 
648     /// @brief check if lanes are consecutives
649     static bool lanesConsecutives(const std::vector<GNELane*>& lanes);
650 
651     /// @brief Parse attribute from XML and show warnings if there are problems parsing it
652     template <typename T>
parseAttributeFromXML(const SUMOSAXAttributes & attrs,const std::string & objectID,const SumoXMLTag tag,const SumoXMLAttr attribute,bool & abort)653     static T parseAttributeFromXML(const SUMOSAXAttributes& attrs, const std::string& objectID, const SumoXMLTag tag, const SumoXMLAttr attribute, bool& abort) {
654         bool parsedOk = true;
655         // declare string values
656         std::string defaultValue, parsedAttribute, warningMessage;
657         // obtain tag properties
658         const auto& tagProperties = getTagProperties(tag);
659         // first check if attribute is deprecated
660         if (tagProperties.isAttributeDeprecated(attribute)) {
661             // show warning if deprecateda ttribute is in the SUMOSAXAttributes
662             if (attrs.hasAttribute(attribute)) {
663                 WRITE_WARNING("Attribute " + toString(attribute) + "' of " + tagProperties.getTagStr() + " is deprecated and will not be loaded.");
664             }
665             // return a dummy value
666             return parse<T>("");
667         }
668         // now check if we're obtaining attribute of an object with an already parsed ID
669         if (objectID != "") {
670             warningMessage = tagProperties.getTagStr() + " with ID '" + objectID + "'";
671         } else {
672             warningMessage = tagProperties.getTagStr();
673         }
674         // check if we're parsing block movement
675         if (attribute == GNE_ATTR_BLOCK_MOVEMENT) {
676             // first check if we can parse
677             if (tagProperties.canBlockMovement()) {
678                 // First check if attribute can be parsed to bool
679                 parsedAttribute = attrs.get<std::string>(attribute, objectID.c_str(), parsedOk, false);
680                 // check that sucesfully parsed attribute can be converted to type double
681                 if (!canParse<bool>(parsedAttribute)) {
682                     abort = true;
683                     // return default value
684                     return parse<T>("0");
685                 } else {
686                     // return readed value
687                     return parse<T>(parsedAttribute);
688                 }
689             } else {
690                 throw ProcessError("Trying to parsing block movement attribute in an AC that cannot be moved");
691             }
692         }
693         // now check if we're parsing a GEO Attribute
694         if (tagProperties.hasGEOPosition() && ((attribute == SUMO_ATTR_LON) || (attribute == SUMO_ATTR_LAT))) {
695             // first check if GEO Attribute is defined
696             if (attrs.hasAttribute(attribute)) {
697                 // First check if attribute can be parsed to string
698                 parsedAttribute = attrs.get<std::string>(attribute, objectID.c_str(), parsedOk, false);
699                 // check that sucesfully parsed attribute can be converted to type double
700                 if (!canParse<double>(parsedAttribute)) {
701                     WRITE_WARNING("Format of GEO attribute '" + toString(attribute) + "' of " +
702                                   warningMessage + " is invalid; Cannot be parsed to float; " + tagProperties.getTagStr() + " cannot be created");
703                     // return default value
704                     return parse<T>("0");
705                 } else {
706                     // return readed value
707                     return parse<T>(parsedAttribute);
708                 }
709             }
710             parsedOk = false;
711             // return default value
712             return parse<T>("0");
713         }
714         // obtain attribute properties (Only for improving efficiency)
715         const auto& attrProperties = tagProperties.getAttributeProperties(attribute);
716         // set a special default value for numerical and boolean attributes (To avoid errors parsing)
717         if (attrProperties.isNumerical() || attrProperties.isBool()) {
718             defaultValue = "0";
719         } else if (attrProperties.isColor()) {
720             defaultValue = "black";
721         } else if (attrProperties.isposition()) {
722             defaultValue = "0,0";
723         }
724         // first check that attribute exists in XML
725         if (attrs.hasAttribute(attribute)) {
726             // First check if attribute can be parsed to string
727             parsedAttribute = attrs.get<std::string>(attribute, objectID.c_str(), parsedOk, false);
728             // check parsed attribute
729             if (!checkParsedAttribute(tagProperties, attrProperties, attribute, defaultValue, parsedAttribute, warningMessage)) {
730                 abort = true;
731             }
732         } else if (tagProperties.canMaskXYZPositions() && (attribute == SUMO_ATTR_POSITION)) {
733             // obtain masked position attribute
734             if (!parseMaskedPositionAttribute(attrs, objectID, tagProperties, attrProperties, parsedAttribute, warningMessage)) {
735                 abort = true;
736             }
737         } else {
738             // if attribute is optional and has a default value, obtain it. In other case, abort.
739             if (attrProperties.isOptional() && attrProperties.hasDefaultValue()) {
740                 parsedAttribute = attrProperties.getDefaultValue();
741             } else {
742                 WRITE_WARNING("Essential " + attrProperties.getDescription() + " attribute '" + toString(attribute) + "' of " +
743                               warningMessage +  " is missing; " + tagProperties.getTagStr() + " cannot be created");
744                 // abort parsing (and creation) of element
745                 abort = true;
746                 // set default value (To avoid errors in parse<T>(parsedAttribute))
747                 parsedAttribute = defaultValue;
748             }
749         }
750         // return parsed attribute
751         return parse<T>(parsedAttribute);
752     }
753 
754     /// @brief function to calculate circle resolution for all circles drawn in drawGL(...) functions
755     static int getCircleResolution(const GUIVisualizationSettings& settings);
756 
757 protected:
758     /// @brief the xml tag to which this attribute carrier corresponds
759     const TagProperties& myTagProperty;
760 
761     /// @brief boolean to check if this AC is selected (instead of GUIGlObjectStorage)
762     bool mySelected;
763 
764     /// @brief dummy TagProperty used for reference some elements (for Example, dummyEdge)
765     static TagProperties dummyTagProperty;
766 
767 private:
768     /// @brief method for setting the attribute and nothing else (used in GNEChange_Attribute)
769     virtual void setAttribute(SumoXMLAttr key, const std::string& value) = 0;
770 
771     /// @brief method for setting the disjoint attribute and nothing else (used in GNEChange_Attribute)
772     virtual void setDisjointAttribute(const int newParameterSet);
773 
774     /// @brief fill Attribute Carriers
775     static void fillAttributeCarriers();
776 
777     /// @brief fill Net Elements
778     static void fillNetElements();
779 
780     /// @brief fill Additionals
781     static void fillAdditionals();
782 
783     /// @brief fill Shapes
784     static void fillShapes();
785 
786     /// @brief fill DemandElements
787     static void fillDemandElements();
788 
789     /// @brief fill Car Following Model of Vehicle Types
790     static void fillCarFollowingModelAttributes();
791 
792     /// @brief fill Junction Model Attronites of Vehicle Types
793     static void fillJunctionModelAttributes();
794 
795     /// @brief parse and check attribute (note: This function is only to improve legilibility)
796     static bool checkParsedAttribute(const TagProperties& tagProperties, const AttributeProperties& attrProperties, const SumoXMLAttr attribute,
797                                      std::string& defaultValue, std::string& parsedAttribute, std::string& warningMessage);
798 
799     /// @brief parse and check masked  (note: This function is only to improve legilibility)
800     static bool parseMaskedPositionAttribute(const SUMOSAXAttributes& attrs, const std::string& objectID, const TagProperties& tagProperties,
801             const AttributeProperties& attrProperties, std::string& parsedAttribute, std::string& warningMessage);
802 
803     /// @brief map with the tags properties
804     static std::map<SumoXMLTag, TagProperties> myTagProperties;
805 
806     /// @brief Invalidated copy constructor.
807     GNEAttributeCarrier(const GNEAttributeCarrier&) = delete;
808 
809     /// @brief Invalidated assignment operator
810     GNEAttributeCarrier& operator=(const GNEAttributeCarrier& src) = delete;
811 };
812 
813 #endif
814 
815 /****************************************************************************/
816 
817