MADARA  3.1.8
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 
19 
20 #ifdef _MADARA_PYTHON_CALLBACKS_
21 
22  #include <boost/python/call.hpp>
23 
24 #endif
25 
26 #ifdef _MADARA_JAVA_
27 
28 #include <jni.h>
29 #include "madara_jni.h"
31 
32 #endif
33 
34 // Ctor
35 
37  const std::string & name,
39  const ComponentNodes & nodes)
40 : CompositeTernaryNode (context.get_logger (), nodes),
41  name_ (name), context_ (context),
42  function_ (context.retrieve_function (name))
43 {
44 
45 }
46 
47 // Dtor
49 {
50 }
51 
54 {
56  record.set_value (name_ + "()");
57  return record;
58 }
59 
65 {
66  // user can always change a function, and we have no control over
67  // what it does. Consequently, a function node cannot be pruned out
68  // under any situation
69  can_change = true;
70 
72 
73  // setup array of record pointers that point to .1, .2, .3, etc.
74  if (nodes_.size () > 0)
75  compiled_args_.resize (nodes_.size ());
76 
77 
78  for (ComponentNodes::size_type i = 0; i < nodes_.size (); ++i)
79  {
80  bool arg_can_change = false;
81  result = nodes_[i]->prune (arg_can_change);
82 
83  if (!arg_can_change && dynamic_cast <LeafNode *> (nodes_[i]) == 0)
84  {
85  delete nodes_[i];
86  nodes_[i] = new LeafNode (*(this->logger_), result);
87  }
88 
89  {
90  // setup the corresponding compiled arg
91  std::stringstream buffer;
92  buffer << ".";
93  buffer << i;
94  compiled_args_[i] = context_.get_record (buffer.str ());
95  }
96  }
97 
98  return result;
99 }
100 
106 {
109 
110  args.resize (nodes_.size ());
111 
112  int j = 0;
113 
114  for (ComponentNodes::iterator i = nodes_.begin (); i != nodes_.end ();
115  ++i, ++j)
116  {
117  args[j] = (*i)->evaluate (settings);
118  *(compiled_args_[j]) = args[j];
119  }
120 
121 
123  variables.context_ = &context_;
124 
126  "Function %s is being called with %d args.\n",
127  this->name_.c_str (), args.size ());
128 
129  // if the user has defined a named function, return that
130  if (function_->is_extern_named ())
131  result = function_->extern_named (name_.c_str (), args, variables);
132 
133  // if the user has defined an unnamed function, return that
134  else if (function_->is_extern_unnamed ())
135  result = function_->extern_unnamed (args, variables);
136 
137 #ifdef _MADARA_JAVA_
138  else if (function_->is_java_callable())
139  {
141  JNIEnv * env = jvm.env;
142 
147  jclass jvarClass = madara::utility::java::find_class (
148  env, "com/madara/Variables");
149  jclass jlistClass = madara::utility::java::find_class (
150  env, "com/madara/KnowledgeList");
151 
152  jmethodID fromPointerCall = env->GetStaticMethodID (jvarClass,
153  "fromPointer", "(J)Lcom/madara/Variables;");
154  jobject jvariables = env->CallStaticObjectMethod (jvarClass,
155  fromPointerCall, (jlong) &variables);
156 
157  // prep to create the KnowledgeList
158  jmethodID listConstructor = env->GetMethodID(jlistClass,
159  "<init>", "([J)V");
160 
161  jlongArray ret = env->NewLongArray((jsize)args.size());
162  jlong * tmp = new jlong [(jsize)args.size()];
163 
164  for (unsigned int x = 0; x < args.size(); x++)
165  {
166  tmp[x] = (jlong) args[x].clone ();
167  }
168 
169  env->SetLongArrayRegion(ret, 0, (jsize)args.size(), tmp);
170  delete [] tmp;
171 
172  // create the KnowledgeList
173  jobject jlist = env->NewObject (jlistClass, listConstructor, ret);
174 
175  // get the filter's class
176  jclass filterClass = env->GetObjectClass(function_->java_object);
177 
178  // get the filter method
179  jmethodID filterMethod = env->GetMethodID (filterClass,
180  "filter",
181  "(Lcom/madara/KnowledgeList;Lcom/madara/Variables;)Lcom/madara/KnowledgeRecord;");
182 
183  // call the filter and hold the result
184  jobject jresult = env->CallObjectMethod (function_->java_object,
185  filterMethod, jlist, jvariables);
186 
187  jmethodID getPtrMethod = env->GetMethodID (
188  env->GetObjectClass(jresult), "getCPtr", "()J");
189  jlong cptr = env->CallLongMethod (jresult, getPtrMethod);
190 
191  bool do_delete = true;
192  //We need to see if they returned an arg we sent them, or a new value
193  for (unsigned int x = 0; x < args.size(); x++)
194  {
195  if (cptr == (jlong)&(args[x]))
196  {
197  do_delete = false;
198  break;
199  }
200  }
201 
203 
204  jvm.env->DeleteLocalRef (jresult);
205  jvm.env->DeleteLocalRef (filterClass);
206  jvm.env->DeleteLocalRef (jlist);
207  jvm.env->DeleteLocalRef (ret);
208  jvm.env->DeleteLocalRef (jvariables);
209  jvm.env->DeleteWeakGlobalRef (jlistClass);
210  jvm.env->DeleteWeakGlobalRef (jvarClass);
211 
212  //if (do_delete)
213  // delete (KnowledgeRecord*)cptr;
214  }
215 #endif
216 
217 #ifdef _MADARA_PYTHON_CALLBACKS_
218  else if (function_->is_python_callable ())
219  return boost::python::call <madara::knowledge::KnowledgeRecord> (
220  function_->python_function.ptr (),
221  boost::ref (args), boost::ref (variables));
222 #endif
223 
224  // otherwise, assume it is a MADARA function
225  else
226  {
227  result = function_->function_contents.evaluate ();
228  }
229 
230  return result;
231 }
232 
233 // accept a visitor
234 void
236 {
237  visitor.visit (*this);
238 }
239 
240 #endif // _MADARA_NO_KARL_
241 
242 #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:96
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.
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.
virtual void accept(Visitor &visitor) const
Accepts a visitor subclassed from the Visitor class.
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:90
static constexpr struct madara::knowledge::tags::string_t string
KnowledgeRecord * get_record(const std::string &key, const KnowledgeReferenceSettings &settings=KnowledgeReferenceSettings())
Retrieves a knowledge record from the key.
CompositeFunctionNode(const std::string &name, madara::knowledge::ThreadSafeContext &context, const ComponentNodes &nodes)
Constructor.
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