1 #ifndef _VarText_h_
2 #define _VarText_h_
3
4 //! @file
5 //! Declares the VarText class.
6
7 #include <map>
8 #include <string>
9 #include <vector>
10
11 #include <boost/serialization/access.hpp>
12 #include <boost/serialization/nvp.hpp>
13
14 #include "Export.h"
15
16 //! Provides a lazy evaluated template string with named variable tags.
17 //!
18 //! VarText is a template string tagged with variable names which are
19 //! substituted with actual data when when calling VarText::GetText().
20 //!
21 //! The format for VarText template string consists of named variable tags
22 //! enclosed by percent signs (%). Depending on the parameter tag used the
23 //! value assigned to a named parameter will be evaluated with the known name of
24 //! the object. When using multiple named variable tags it is possible to
25 //! separate the tag with an double colon (:) from an identifing label. The
26 //! label should be limited to lower case latin characters and the underscore.
27 //!
28 //! See @ref variable_tags "Variable Tags" for a list of supported variable
29 //! tags.
30 //!
31 //!
32 //! For example: When assigning template string:
33 //!
34 //! On %planet%: the %building% has been produced.
35 //!
36 //! to a VarText instance it declares the two named variable tags @e %%planet%
37 //! and @e %%building%.
38 //!
39 //! By calling VarText::AddVariable() identifiers can be assigned to those named
40 //! variable tags. For example:
41 //!
42 //! ```{.cpp}
43 //! // the_capital_planet.VisibleName() == "Garmillas II"
44 //! var_text.AddVariable("planet", the_capital_planet.ID());
45 //! // the_imperial_palace.VisibleName() == "Imperial Palace"
46 //! var_text.AddVariable("building", the_imperial_palace.ID());
47 //! ```
48 //!
49 //! Now when calling VarText::GetText() the references are replaced with the
50 //! actual object name (assuming the resolver can see all the objects):
51 //!
52 //! On Garmillas II: the Imperial Palace has been produced.
53 //!
54 //! In case there are multiple named variable tags of the same type it is
55 //! possible to add labels to distinguish those. For example the template
56 //! string:
57 //!
58 //! In %system%: "%fleet:defender%" was overrun by "%fleet:attacker%"
59 //!
60 //! where the name variable tags are set to:
61 //!
62 //! ```{.cpp}
63 //! // the_battleground.VisibleName() == "Balun"
64 //! var_text.AddVariable("system", the_battleground.ID());
65 //! // the_defender_fleet.VisibleName() == "Great Garmillas Armada"
66 //! var_text.AddVariable("fleet:defender", the_defender_fleet.ID());
67 //! // the_attacker_fleet.VisibleName() == "UNCN Special Ops fleet"
68 //! var_text.AddVariable("fleet:attacker", the_attacker_fleet.ID());
69 //! ```
70 //!
71 //! would resolve into:
72 //!
73 //! In Balun: "Geat Garmillas Armada" was overrun by "UNCN Special Ops fleet"
74 class FO_COMMON_API VarText {
75 public:
76 //! Create a VarText instance with an empty #m_template_string.
77 VarText();
78
79 //! Create a VarText instance from the given @p template_string.
80 //!
81 //! @param template_string @see #m_template_string.
82 //! @param stringtable_lookup @see #m_stringtable_lookup_flag
83 explicit VarText(const std::string& template_string, bool stringtable_lookup = true);
84
85 //! Return the text generated after substituting all variables.
86 const std::string& GetText() const;
87
88 //! Return if the text substitution was successful.
89 bool Validate() const;
90
91 //! Return the #m_template_string
GetTemplateString()92 const std::string& GetTemplateString() const
93 { return m_template_string; }
94
95 //! Return the #m_stringtable_lookup_flag
GetStringtableLookupFlag()96 bool GetStringtableLookupFlag() const
97 { return m_stringtable_lookup_flag; }
98
99 //! Return the variables available for substitution.
100 std::vector<std::string> GetVariableTags() const;
101
102 //! Set the #m_template_string to the given @p template_string.
103 //!
104 //! @param template_string @see #m_template_string.
105 //! @param stringtable_lookup @see #m_stringtable_lookup_flag
106 void SetTemplateString(const std::string& template_string, bool stringtable_lookup = true);
107
108 //! Assign @p data to a given @p tag.
109 //!
110 //! The @p data should match @p tag as listed in
111 //! @ref variable_tags "Variable tags".
112 //!
113 //! @param tag
114 //! Tag of the #m_variables set, may be labled.
115 //! @param data
116 //! Data value of the #m_variables set.
117 void AddVariable(const std::string& tag, const std::string& data);
118
119 //! @name Variable tags
120 //! @anchor variable_tags
121 //!
122 //! Tag strings that are recognized and replaced in VarText with the
123 //! corresponding reference to an specific game entity.
124 //!
125 //! @{
126
127 //! Variable value is a StringTable key.
128 static const std::string TEXT_TAG;
129 //! Variable value is a literal string.
130 static const std::string RAW_TEXT_TAG;
131 //! Variable value is a Planet::ID().
132 static const std::string PLANET_ID_TAG;
133 //! Variable value is a System::ID().
134 static const std::string SYSTEM_ID_TAG;
135 //! Variable value is a Ship::ID().
136 static const std::string SHIP_ID_TAG;
137 //! Variable value is a Fleet::ID().
138 static const std::string FLEET_ID_TAG;
139 //! Variable value is a Building::ID().
140 static const std::string BUILDING_ID_TAG;
141 //! Variable value is a Field::ID().
142 static const std::string FIELD_ID_TAG;
143 //! Variable value represents a CombatLog.
144 static const std::string COMBAT_ID_TAG;
145 //! Variable value is an Empire::EmpireID().
146 static const std::string EMPIRE_ID_TAG;
147 //! Variable value is a ShipDesign::ID().
148 static const std::string DESIGN_ID_TAG;
149 //! Variable value is a ShipDesign::ID() of a predefined ShipDesign.
150 static const std::string PREDEFINED_DESIGN_TAG;
151 //! Variable value is a Tech::Name().
152 static const std::string TECH_TAG;
153 //! Variable value is a BuildingType::Name().
154 static const std::string BUILDING_TYPE_TAG;
155 //! Variable value is a Special::Name().
156 static const std::string SPECIAL_TAG;
157 //! Variable value is a ShipHull::Name().
158 static const std::string SHIP_HULL_TAG;
159 //! Variable value is a ShipPart::Name().
160 static const std::string SHIP_PART_TAG;
161 //! Variable value is a Species::Name().
162 static const std::string SPECIES_TAG;
163 //! Variable value is a FieldType::Name().
164 static const std::string FIELD_TYPE_TAG;
165 //! Variable value is a predefined MeterType string representation.
166 static const std::string METER_TYPE_TAG;
167
168 //! @}
169
170 protected:
171 //! Combines the template with the variables contained in object to
172 //! create a string with variables replaced with text.
173 void GenerateVarText() const;
174
175 //! The template text used by this VarText, into which variables are
176 //! substituted to render the text as user-readable.
177 //!
178 //! @see #m_stringtable_lookup_flag
179 std::string m_template_string;
180
181 //! If true the #m_template_string will be looked up in the stringtable
182 //! prior to substitution for variables.
183 bool m_stringtable_lookup_flag = false;
184
185 //! Maps variable tags into values, which are used during text substitution.
186 std::map<std::string, std::string> m_variables;
187
188 //! #m_template_string with applied #m_variables substitute.
189 mutable std::string m_text;
190
191 //! True if the #m_template_string stubstitution was executed without
192 //! errors.
193 mutable bool m_validated = false;
194
195 private:
196 friend class boost::serialization::access;
197 template <typename Archive>
198 void serialize(Archive& ar, const unsigned int version);
199 };
200
201 template <typename Archive>
serialize(Archive & ar,const unsigned int version)202 void VarText::serialize(Archive& ar, const unsigned int version)
203 {
204 ar & BOOST_SERIALIZATION_NVP(m_template_string)
205 & BOOST_SERIALIZATION_NVP(m_stringtable_lookup_flag)
206 & BOOST_SERIALIZATION_NVP(m_variables);
207 }
208
209 #endif // _VarText_h_
210