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