1 /**
2  * @cond doxygenLibsbmlInternal
3  *
4  * @file    ASTBasePlugin.h
5  * @brief   Definition of ASTBasePlugin, the base class of extension entities
6  *          plugged in AST derived classes in the SBML Core package.
7  * @author  Sarah Keating
8  * @author  Lucian Smith
9  *
10  *
11  * <!--------------------------------------------------------------------------
12  * This file is part of libSBML.  Please visit http://sbml.org for more
13  * information about SBML, and the latest version of libSBML.
14  *
15  * Copyright (C) 2020 jointly by the following organizations:
16  *     1. California Institute of Technology, Pasadena, CA, USA
17  *     2. University of Heidelberg, Heidelberg, Germany
18  *     3. University College London, London, UK
19  *
20  * Copyright (C) 2019 jointly by the following organizations:
21  *     1. California Institute of Technology, Pasadena, CA, USA
22  *     2. University of Heidelberg, Heidelberg, Germany
23  *
24  * Copyright (C) 2013-2018 jointly by the following organizations:
25  *     1. California Institute of Technology, Pasadena, CA, USA
26  *     2. EMBL European Bioinformatics Institute (EMBL-EBI), Hinxton, UK
27  *     3. University of Heidelberg, Heidelberg, Germany
28  *
29  * Copyright (C) 2009-2012 jointly by the following organizations:
30  *     1. California Institute of Technology, Pasadena, CA, USA
31  *     2. EMBL European Bioinformatics Institute (EMBL-EBI), Hinxton, UK
32  *
33  * Copyright (C) 2006-2008 by the California Institute of Technology,
34  *     Pasadena, CA, USA
35  *
36  * Copyright (C) 2002-2005 jointly by the following organizations:
37  *     1. California Institute of Technology, Pasadena, CA, USA
38  *     2. Japan Science and Technology Agency, Japan
39  *
40  * This library is free software; you can redistribute it and/or modify it
41  * under the terms of the GNU Lesser General Public License as published by
42  * the Free Software Foundation.  A copy of the license agreement is provided
43  * in the file named "LICENSE.txt" included with this software distribution
44  * and also available online as http://sbml.org/software/libsbml/license.html
45  * ------------------------------------------------------------------------ -->
46  *
47  * @class ASTBasePlugin
48  * @sbmlbrief{core} Base class for extensions that plug into AST classes.
49  *
50  * @htmlinclude not-sbml-warning.html
51  */
52 
53 #ifndef ASTBasePlugin_h
54 #define ASTBasePlugin_h
55 
56 #include <sbml/common/libsbml-config-common.h>
57 
58 #include <sbml/common/sbmlfwd.h>
59 
60 #ifdef __cplusplus
61 #include <vector>
62 #include <string>
63 #include <map>
64 #include <sbml/math/ASTNodeType.h>
65 
66 
67 #include <sbml/math/L3ParserSettings.h>
68 #include <sbml/SBMLTransforms.h>
69 
70 LIBSBML_CPP_NAMESPACE_BEGIN
71 
72 class UnitDefinition;
73 class UnitFormulaFormatter;
74 class ArgumentsUnitsCheck;
75 
76 
77 struct ASTNodeValues_t {
78   std::string name;
79   ASTNodeType_t type;
80   bool isFunction;
81   std::string csymbolURL;
82   AllowedChildrenType_t allowedChildrenType;
83   std::vector<unsigned int> numAllowedChildren;
84 };
85 
86 
87 class LIBSBML_EXTERN ASTBasePlugin
88 {
89 public:
90 
91 //#ifndef SWIG
92 //  typedef std::pair<double, bool>   ValueSet;
93 //  typedef std::map<const std::string, ValueSet> IdValueMap;
94 //#endif
95   virtual const std::string& getStringFor(ASTNodeType_t type) const;
96   virtual const char* getConstCharFor(ASTNodeType_t type) const;
97   virtual const char* getConstCharCsymbolURLFor(ASTNodeType_t type) const;
98   virtual ASTNodeType_t getASTNodeTypeFor(const std::string& symbol) const;
99   virtual ASTNodeType_t getASTNodeTypeForCSymbolURL(const std::string& url) const;
100   virtual bool hasCorrectNamespace(SBMLNamespaces* namespaces) const;
101   virtual bool defines(ASTNodeType_t type) const;
102   virtual bool defines(const std::string& name, bool strCmpIsCaseSensitive = false) const;
103   virtual bool isFunction(ASTNodeType_t type) const;
104   virtual std::vector<unsigned int> getNumAllowedChildren(ASTNodeType_t type) const;
105   virtual bool isLogical(ASTNodeType_t type) const;
106   virtual bool isMathMLNodeTag(const std::string& node) const;
107   virtual bool isMathMLNodeTag(ASTNodeType_t type) const;
108   virtual ExtendedMathType_t getExtendedMathType() const;
109   virtual double evaluateASTNode(const ASTNode * node, const Model * m = NULL) const;
110   virtual UnitDefinition * getUnitDefinitionFromPackage(UnitFormulaFormatter* uff, const ASTNode * node, bool inKL, int reactNo) const;
111 
112   const ASTNodeValues_t* getASTNodeValue(unsigned int n) const;
113   /**
114    * Check if the node type is known to be allowed inside function definitions.
115    *
116    * Function definitions must be able to be evaluated without resort to outside information.
117    * Therefore, some ASTNodes (like AST_TIME and AST_FUNCTION_RATE_OF) are disallowed
118    * from appearing there.  This function checks whether this is true for a given type:
119    * a return value of '-1' means the plugin has no knowledge of that type; a return
120    * value of '1' means the plugin knows that the type is indeed allowed, and a
121    * return value of '0' means that the plugin knows that the type is not allowed.
122    */
123   virtual int allowedInFunctionDefinition(ASTNodeType_t type) const;
124   //virtual void checkUnits(ArgumentsUnitsCheck* auc, const Model& m, const ASTNode& node, const SBase & sb, bool inKL, int reactNo) const;
125 
126 
127   /**
128   * Destroy this object.
129   */
130   virtual ~ASTBasePlugin();
131 
132 
133   /**
134   * Assignment operator for ASTBasePlugin.
135   *
136   * @param orig the object whose values are used as the basis of the
137   * assignment.
138   */
139   ASTBasePlugin& operator=(const ASTBasePlugin& orig);
140 
141 
142   /**
143   * Creates and returns a deep copy of this ASTBasePlugin object.
144   *
145   * @return the (deep) copy of this ASTBasePlugin object.
146   */
147   virtual ASTBasePlugin* clone() const;
148 
149 
150   /**
151   * Returns the XML namespace (URI) of the package extension
152   * of this plugin object.
153   *
154   * @return the URI of the package extension of this plugin object.
155   */
156   const std::string& getElementNamespace() const;
157 
158 
159   /**
160   * Returns the prefix of the package extension of this plugin object.
161   *
162   * @return the prefix of the package extension of this plugin object.
163   */
164   virtual const std::string& getPrefix() const;
165 
166 
167   /**
168   * Returns the package name of this plugin object.
169   *
170   * @return the package name of this plugin object.
171   */
172   virtual const std::string& getPackageName() const;
173 
174 
175 
176 
177   /* open doxygen comment */
178 
179   // ---------------------------------------------------------
180   //
181   // virtual functions (internal implementation) which should
182   // be overridden by subclasses.
183   //
184   // ---------------------------------------------------------
185 
186   virtual int setSBMLExtension(const SBMLExtension* ext);
187 
188   virtual int setPrefix(const std::string& prefix);
189   /**
190   * Sets the parent SBML object of this plugin object to
191   * this object and child elements (if any).
192   * (Creates a child-parent relationship by this plugin object)
193   *
194   * This function is called when this object is created by
195   * the parent element.
196   * Subclasses must override this this function if they have one
197   * or more child elements. Also, ASTBasePlugin::connectToParent(@if java SBase@endif)
198   * must be called in the overridden function.
199   *
200   * @param sbase the SBase object to use.
201   *
202   * @see setSBMLDocument
203   * @see enablePackageInternal
204   */
205   virtual void connectToParent(ASTNode *astbase);
206 
207 
208   /**
209   * Enables/Disables the given package with child elements in this plugin
210   * object (if any).
211   * (This is an internal implementation invoked from
212   *  SBase::enablePackageInternal() function)
213   *
214   * Subclasses which contain one or more SBase derived elements should
215   * override this function if elements defined in them can be extended by
216   * some other package extension.
217   *
218   * @see setSBMLDocument
219   * @see connectToParent
220   */
221   virtual void enablePackageInternal(const std::string& pkgURI,
222     const std::string& pkgPrefix, bool flag);
223 
224 
225   virtual bool stripPackage(const std::string& pkgPrefix, bool flag);
226 
227 
228   /* end doxygen comment */
229 
230   // ----------------------------------------------------------
231 
232 
233   /**
234   * Returns the URI to which this element belongs to.
235   * For example, all elements that belong to SBML Level&nbsp;3 Version&nbsp;1 Core
236   * must would have the URI "http://www.sbml.org/sbml/level3/version1/core";
237   * all elements that belong to Layout Extension Version&nbsp;1 for SBML Level&nbsp;3
238   * Version&nbsp;1 Core must would have the URI
239   * "http://www.sbml.org/sbml/level3/version1/layout/version1/"
240   *
241   * Unlike getElementNamespace, this function first returns the URI for this
242   * element by looking into the SBMLNamespaces object of the document with
243   * the its package name. if not found it will return the result of
244   * getElementNamespace
245   *
246   * @return the URI of this ASTBasePlugin.
247   *
248   * @see getPackageName
249   * @see getElementNamespace
250   * @see SBMLDocument::getSBMLNamespaces
251   * @see getSBMLDocument
252   */
253   std::string getURI() const;
254 
255   /* open doxygen comment */
256 
257   /**
258   * Returns the parent ASTNode object to which this plugin
259   * object connected.
260   *
261   * @return the parent ASTNode object to which this plugin
262   * object connected.
263   */
264   ASTNode* getParentASTObject();
265 
266   /* end doxygen comment */
267 
268   /* open doxygen comment */
269 
270   /**
271   * Returns the parent ASTNode object to which this plugin
272   * object connected.
273   *
274   * @return the parent ASTNode object to which this plugin
275   * object connected.
276   */
277   const ASTNode* getParentASTObject() const;
278 
279 
280   /* end doxygen comment */
281 
282   /**
283   * Sets the XML namespace to which this element belongs to.
284   * For example, all elements that belong to SBML Level&nbsp;3 Version&nbsp;1 Core
285   * must set the namespace to "http://www.sbml.org/sbml/level3/version1/core";
286   * all elements that belong to Layout Extension Version&nbsp;1 for SBML Level&nbsp;3
287   * Version&nbsp;1 Core must set the namespace to
288   * "http://www.sbml.org/sbml/level3/version1/layout/version1/"
289   *
290   * @copydetails doc_returns_success_code
291   * @li @sbmlconstant{LIBSBML_OPERATION_SUCCESS, OperationReturnValues_t}
292   * @li @sbmlconstant{LIBSBML_INVALID_ATTRIBUTE_VALUE, OperationReturnValues_t}
293   */
294   int setElementNamespace(const std::string &uri);
295 
296   /**
297   * Returns the SBML level of the package extension of
298   * this plugin object.
299   *
300   * @return the SBML level of the package extension of
301   * this plugin object.
302   */
303   unsigned int getLevel() const;
304 
305 
306   /**
307   * Returns the SBML version of the package extension of
308   * this plugin object.
309   *
310   * @return the SBML version of the package extension of
311   * this plugin object.
312   */
313   unsigned int getVersion() const;
314 
315 
316   /**
317   * Returns the package version of the package extension of
318   * this plugin object.
319   *
320   * @return the package version of the package extension of
321   * this plugin object.
322   */
323   unsigned int getPackageVersion() const;
324 
325 
326 
327   /* open doxygen comment */
328   virtual SBMLNamespaces * getSBMLNamespaces() const;
329 
330 
331 
332   /* end doxygen comment */
333   friend class L3ParserSettings;
334   friend class ASTNode;
335 
336   //The following functions don't do anything on their own, and are meant to be overridden by relevant plugins.
337   /**
338   * Renames all the SIdRef attributes on this node and its child nodes.
339   *
340   * @param oldid the old identifier.
341   * @param newid the new identifier.
342   */
343   virtual void renameSIdRefs(const std::string& oldid, const std::string& newid);
344 
345 
346   /**
347   * Renames all the UnitSIdRef attributes on this node and its child nodes.
348   *
349   * The only place UnitSIDRefs appear in MathML <code>&lt;cn&gt;</code>
350   * elements, so the effects of this method are limited to that.
351   *
352   * @param oldid the old identifier.
353   * @param newid the new identifier.
354   */
355   virtual void renameUnitSIdRefs(const std::string& oldid, const std::string& newid);
356 
357 
358   /** @cond doxygenLibsbmlInternal */
359   /**
360   * Replace any nodes of type AST_NAME with the name 'id' from the child
361   * 'math' object with the provided ASTNode.
362   *
363   */
364   virtual void replaceIDWithFunction(const std::string& id, const ASTNode* function);
365 
366   /**
367   * This function checks the provided ASTNode function to see if it is a
368   * known function with the wrong number of arguments.  If so, 'error' is
369   * set and '-1' is returned.  If it has the correct number of arguments,
370   * '1' is returned.  If the plugin knows nothing about the function, '0'
371   * is returned.
372   */
373   virtual int checkNumArguments(const ASTNode* function, std::stringstream& error) const;
374   /**
375   * Get the precedence of this package function, or @c -1 if unknown
376   */
377   virtual int getL3PackageInfixPrecedence() const;
378 
379   /**
380   * This function checks the provided ASTNode function to see if it is a
381   * known function with the wrong number of arguments
382   */
383   virtual bool hasCorrectNumArguments(const ASTNode* function) const;
384   /**
385   * Returns @c true if this is a package function which should be written
386   * special syntax that the package knows about, @c false otherwise.
387   */
388   virtual bool hasPackageOnlyInfixSyntax() const;
389 
390   /**
391   * Returns @c true if this is a package function which should be written
392   * special syntax that the package knows about, @c false otherwise.
393   */
394   virtual bool hasUnambiguousPackageInfixGrammar(const ASTNode *child) const;
395 
396   /**
397   * Returns @c true if this is a package function which should be written as
398   * "functionname(argumentlist)", @c false otherwise.
399   */
400   virtual bool isPackageInfixFunction() const;
401 
402 
403 protected:
404   /* open doxygen comment */
405   /**
406   * Constructor. Creates an ASTBasePlugin object with the URI and
407   * prefix of an package extension.
408   */
409   ASTBasePlugin(const std::string &uri);
410 
411   ASTBasePlugin();
412 
413   /**
414   * Copy constructor. Creates a copy of this SBase object.
415   *
416   * @param orig the instance to copy.
417   */
418   ASTBasePlugin(const ASTBasePlugin& orig);
419 
420   /**
421   * Visits the given ASTNode_t and continues the inorder traversal for nodes whose syntax are determined by packages.
422   */
423   virtual void visitPackageInfixSyntax(const ASTNode *parent,
424     const ASTNode *node,
425     StringBuffer_t  *sb,
426     const L3ParserSettings* settings) const;
427 
428 
429   /**
430   * The generic parsing function for grammar lines that packages recognize, but not core.
431   * When a package recognizes the 'type', it will parse and return the correct ASTNode.
432   * If it does not recognize the 'type', or if the arguments are incorrect, NULL is returend.
433   */
434   virtual ASTNode* parsePackageInfix(L3ParserGrammarLineType_t type,
435     std::vector<ASTNode*> *nodeList = NULL, std::vector<std::string*> *stringList = NULL,
436     std::vector<double> *doubleList = NULL) const;
437 
438 
439   /**
440   * The user input a string of the form "name(...)", and we want to know if
441   * 'name' is recognized by a package as being a particular function.  We already
442   * know that it is not used in the Model as a FunctionDefinition.  Should do
443   * caseless string comparison.  Return the type of the function, or @sbmlconstant{AST_UNKNOWN, ASTNodeType_t}
444   * if nothing found.
445   */
446   virtual ASTNodeType_t getPackageFunctionFor(const std::string& name, bool strCmpIsCaseSensitive = false) const;
447 
448   /**
449   * The user input a string of the form "name" with no parentheses, and we want to know if
450   * 'name' is recognized by a package as being a particular symbol.  We already
451   * know that it is not used in the Model as the id of a mathematically-meaningful element.  Should do
452   * caseless string comparison.  Return the type of the symbol, or @sbmlconstant{AST_UNKNOWN, ASTNodeType_t}
453   * if nothing found.
454   */
455   virtual ASTNodeType_t getPackageSymbolFor(const std::string& name, bool strCmpIsCaseSensitive = false) const;
456 
457   /*-- data members --*/
458 
459   //
460   // An SBMLExtension derived object of corresponding package extension
461   // The owner of this object is SBMLExtensionRegistry class.
462   //
463   const SBMLExtension  *mSBMLExt;
464 
465   //
466   // Parent ASTNode object to which this plugin object
467   // connected.
468   //
469   ASTNode                *mParentASTNode;
470 
471   //
472   // XML namespace of corresponding package extension
473   //
474   std::string          mURI;
475 
476   //
477   // SBMLNamespaces derived object of this plugin object.
478   //
479   SBMLNamespaces      *mSBMLNS;
480 
481   //
482   // Prefix of corresponding package extension
483   //
484   std::string          mPrefix;
485 
486     std::vector<ASTNodeValues_t> mPkgASTNodeValues;
487     ExtendedMathType_t mExtendedMathType;
488   /* end doxygen comment */
489 };
490 
491 LIBSBML_CPP_NAMESPACE_END
492 
493 #endif  /* __cplusplus */
494 
495 
496 
497 
498 #endif  /* ASTBasePlugin_h */
499 /** @endcond */
500 
501