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