MADARA  3.2.3
CompositeFunctionNode.cpp
Go to the documentation of this file.
1 /* -*- C++ -*- */
2 #ifndef _FUNCTION_NODE_CPP_
3 #define _FUNCTION_NODE_CPP_
4 
5 #ifndef _MADARA_NO_KARL_
6 
7 #include <iostream>
8 #include <sstream>
9 
15 
16 
20 
21 #ifdef _MADARA_PYTHON_CALLBACKS_
22 
23  #include <boost/python/call.hpp>
24 
25 #endif
26 
27 #ifdef _MADARA_JAVA_
28 
29 #include <jni.h>
30 #include "madara_jni.h"
32 
33 #endif
34 
35 // Ctor
36 
38  const std::string & name,
40  const ComponentNodes & nodes)
41 : CompositeTernaryNode (context.get_logger (), nodes),
42  name_ (name), context_ (context),
43  function_ (context.retrieve_function (name))
44 {
45 
46 }
47 
48 // Dtor
50 {
51 }
52 
55 {
57  record.set_value (name_ + "()");
58  return record;
59 }
60 
66 {
67  // user can always change a function, and we have no control over
68  // what it does. Consequently, a function node cannot be pruned out
69  // under any situation
70  can_change = true;
71 
73 
74  // setup array of record pointers that point to .1, .2, .3, etc.
75  if (nodes_.size () > 0)
76  compiled_args_.resize (nodes_.size ());
77 
78 
79  for (ComponentNodes::size_type i = 0; i < nodes_.size (); ++i)
80  {
81  bool arg_can_change = false;
82  result = nodes_[i]->prune (arg_can_change);
83 
84  if (!arg_can_change && dynamic_cast <LeafNode *> (nodes_[i]) == 0)
85  {
86  delete nodes_[i];
87  nodes_[i] = new LeafNode (*(this->logger_), result);
88  }
89 
90  {
91  // setup the corresponding compiled arg
92  std::stringstream buffer;
93  buffer << ".";
94  buffer << i;
95  compiled_args_[i] = context_.get_record (buffer.str ());
96  }
97  }
98 
99  return result;
100 }
101 
107 {
110 
111  args.resize (nodes_.size ());
112 
113  int j = 0;
114 
115  for (ComponentNodes::iterator i = nodes_.begin (); i != nodes_.end ();
116  ++i, ++j)
117  {
118  args[j] = (*i)->evaluate (settings);
119  *(compiled_args_[j]) = args[j];
120  }
121 
122 
124  variables.context_ = &context_;
125 
127  "Function %s is being called with %d args.\n",
128  this->name_.c_str (), args.size ());
129 
130  // if the user has defined a named function, return that
131  if (function_->is_extern_named ())
132  result = function_->extern_named (name_.c_str (), args, variables);
133 
134  // if the user has defined an unnamed function, return that
135  else if (function_->is_extern_unnamed ())
136  result = function_->extern_unnamed (args, variables);
137 
138 #ifdef _MADARA_JAVA_
139  else if (function_->is_java_callable())
140  {
142  JNIEnv * env = jvm.env;
143 
148  jclass jvarClass = madara::utility::java::find_class (
149  env, "ai/madara/knowledge/Variables");
150  jclass jlistClass = madara::utility::java::find_class (
151  env, "ai/madara/knowledge/KnowledgeList");
152 
153  jmethodID fromPointerCall = env->GetStaticMethodID (jvarClass,
154  "fromPointer", "(J)Lai/madara/knowledge/Variables;");
155  jobject jvariables = env->CallStaticObjectMethod (jvarClass,
156  fromPointerCall, (jlong) &variables);
157 
158  // prep to create the KnowledgeList
159  jmethodID listConstructor = env->GetMethodID(jlistClass,
160  "<init>", "([J)V");
161 
162  jlongArray ret = env->NewLongArray((jsize)args.size());
163  jlong * tmp = new jlong [(jsize)args.size()];
164 
165  for (unsigned int x = 0; x < args.size(); x++)
166  {
167  tmp[x] = (jlong) args[x].clone ();
168  }
169 
170  env->SetLongArrayRegion(ret, 0, (jsize)args.size(), tmp);
171  delete [] tmp;
172 
173  // create the KnowledgeList
174  jobject jlist = env->NewObject (jlistClass, listConstructor, ret);
175 
176  // get the filter's class
177  jclass filterClass = env->GetObjectClass(function_->java_object);
178 
179  // get the filter method
180  jmethodID filterMethod = env->GetMethodID (filterClass,
181  "filter",
182  "(Lai/madara/knowledge/KnowledgeList;"
183  "Lai/madara/knowledge/Variables;)Lai/madara/knowledge/KnowledgeRecord;");
184 
185  // call the filter and hold the result
186  jobject jresult = env->CallObjectMethod (function_->java_object,
187  filterMethod, jlist, jvariables);
188 
189  jmethodID getPtrMethod = env->GetMethodID (
190  env->GetObjectClass(jresult), "getCPtr", "()J");
191  jlong cptr = env->CallLongMethod (jresult, getPtrMethod);
192 
194 
195  jvm.env->DeleteLocalRef (jresult);
196  jvm.env->DeleteLocalRef (filterClass);
197  jvm.env->DeleteLocalRef (jlist);
198  jvm.env->DeleteLocalRef (ret);
199  jvm.env->DeleteLocalRef (jvariables);
200  jvm.env->DeleteWeakGlobalRef (jlistClass);
201  jvm.env->DeleteWeakGlobalRef (jvarClass);
202  }
203 #endif
204 
205 #ifdef _MADARA_PYTHON_CALLBACKS_
206  else if (function_->is_python_callable ())
207  return boost::python::call <madara::knowledge::KnowledgeRecord> (
208  function_->python_function.ptr (),
209  boost::ref (args), boost::ref (variables));
210 #endif
211 
212  else if (function_->is_uninitialized ())
213  {
215  "CompositeFunctionNode:"
216  "KARL RUNTIME EXCEPTION: "
217  "Attempt at calling an undefined function\n");
218 
219  throw KarlException ("CompositeFunctionNode:"
220  "KARL RUNTIME EXCEPTION: "
221  "Attempt at calling an undefined function");
222  }
223  // otherwise, assume it is a MADARA function
224  else
225  {
226  result = function_->function_contents.evaluate ();
227  }
228 
229  return result;
230 }
231 
232 // accept a visitor
233 void
235 {
236  visitor.visit (*this);
237 }
238 
239 #endif // _MADARA_NO_KARL_
240 
241 #endif /* _FUNCTION_NODE_CPP_ */
This class encapsulates an entry in a KnowledgeBase.
JNIEnv * env
The Java environment.
Definition: Acquire_VM.h:58
void deep_copy(const KnowledgeRecord &source)
Creates a deep copy of the knowledge record.
This class encapsulates attaching and detaching to a VM.
Definition: Acquire_VM.h:24
knowledge::KnowledgeRecord(* extern_named)(const char *, FunctionArguments &, Variables &)
Definition: Functions.h:157
std::vector< knowledge::KnowledgeRecord * > compiled_args_
virtual madara::knowledge::KnowledgeRecord item(void) const
Returns the printable character of the node.
knowledge::KnowledgeRecord(* extern_unnamed)(FunctionArguments &, Variables &)
Definition: Functions.h:161
std::deque< ComponentNode * > ComponentNodes
a vector of Component Nodes
logger::Logger * logger_
handle the context
Definition: ComponentNode.h:97
This class stores variables and their values for use by any entity needing state information in a thr...
virtual madara::knowledge::KnowledgeRecord prune(bool &can_change)
Prunes the expression tree of unnecessary nodes.
bool is_python_callable(void) const
Definition: Functions.h:216
Defines a node that contains a madara::knowledge::KnowledgeRecord::Integer value. ...
Definition: LeafNode.h:23
std::vector< KnowledgeRecord > FunctionArguments
void set_value(const KnowledgeRecord &new_value)
Sets the value from another KnowledgeRecord, does not copy clock and write_quality.
bool is_uninitialized(void) const
Definition: Functions.h:151
virtual void accept(Visitor &visitor) const
Accepts a visitor subclassed from the Visitor class.
static struct madara::knowledge::tags::string_t string
virtual madara::knowledge::KnowledgeRecord evaluate(const madara::knowledge::KnowledgeUpdateSettings &settings)
Evaluates the expression tree.
#define madara_logger_ptr_log(logger, level,...)
Fast version of the madara::logger::log method for Logger pointers.
Definition: Logger.h:32
bool is_extern_named(void) const
Definition: Functions.h:136
ThreadSafeContext * context_
Variables context that is directly used by the KaRL engine.
Abstract base class for all visitors to all classes that derive from ComponentNode.
Definition: Visitor.h:91
boost::python::object python_function
Definition: Functions.h:221
An exception for unrecoverable KaRL compilation issues.
Definition: KarlException.h:18
bool is_java_callable(void) const
Definition: Functions.h:189
CompositeFunctionNode(const std::string &name, madara::knowledge::ThreadSafeContext &context, const ComponentNodes &nodes)
Constructor.
KnowledgeRecord * get_record(const std::string &key, const KnowledgeReferenceSettings &settings=KnowledgeReferenceSettings())
Retrieves a knowledge record from the key.
Settings for applying knowledge updates.
virtual void visit(const LeafNode &node)=0
Visit a LeafNode.
void resize(size_t new_size)
resizes an array to a new size
Provides an interface for external functions into the MADARA KaRL variable settings.
bool is_extern_unnamed(void) const
Definition: Functions.h:131
madara::knowledge::KnowledgeRecord evaluate(const madara::knowledge::KnowledgeUpdateSettings &settings=knowledge::KnowledgeUpdateSettings())
Evaluates the expression tree.
madara::expression::ExpressionTree function_contents
Definition: Functions.h:165